react-native-inapp-inspector 2.0.3 → 2.0.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/android/.gradle/8.9/checksums/checksums.lock +0 -0
- package/android/.gradle/8.9/checksums/md5-checksums.bin +0 -0
- package/android/.gradle/8.9/checksums/sha1-checksums.bin +0 -0
- package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/8.9/executionHistory/executionHistory.lock +0 -0
- package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.9/gc.properties +0 -0
- package/android/.gradle/9.2.0/checksums/checksums.lock +0 -0
- package/android/.gradle/9.2.0/fileChanges/last-build.bin +0 -0
- package/android/.gradle/9.2.0/fileHashes/fileHashes.bin +0 -0
- package/android/.gradle/9.2.0/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/9.2.0/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/build/reports/problems/problems-report.html +659 -0
- package/dist/commonjs/components/Inspector/InspectorHeader.js +87 -50
- package/dist/commonjs/components/Inspector/MainScreen.js +1 -0
- package/dist/commonjs/components/Inspector/NetworkTab.js +317 -12
- package/dist/commonjs/components/Inspector/NpmUpdateToast.js +88 -39
- package/dist/commonjs/components/Inspector/SettingsPanel.js +525 -359
- package/dist/commonjs/components/Inspector/UpdateAvailableModal.d.ts +8 -0
- package/dist/commonjs/components/Inspector/UpdateAvailableModal.js +469 -0
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/helpers/searchQueryParser.d.ts +8 -3
- package/dist/commonjs/helpers/searchQueryParser.js +85 -31
- package/dist/commonjs/helpers/telemetry.js +4 -4
- package/dist/commonjs/index.js +58 -7
- package/dist/commonjs/types/interfaces.d.ts +9 -0
- package/dist/esm/components/Inspector/InspectorHeader.js +87 -50
- package/dist/esm/components/Inspector/MainScreen.js +1 -0
- package/dist/esm/components/Inspector/NetworkTab.js +317 -12
- package/dist/esm/components/Inspector/NpmUpdateToast.js +88 -39
- package/dist/esm/components/Inspector/SettingsPanel.js +526 -360
- package/dist/esm/components/Inspector/UpdateAvailableModal.d.ts +8 -0
- package/dist/esm/components/Inspector/UpdateAvailableModal.js +432 -0
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/helpers/searchQueryParser.d.ts +8 -3
- package/dist/esm/helpers/searchQueryParser.js +85 -31
- package/dist/esm/helpers/telemetry.js +4 -4
- package/dist/esm/index.js +58 -7
- package/dist/esm/types/interfaces.d.ts +9 -0
- package/package.json +1 -1
package/dist/commonjs/index.js
CHANGED
|
@@ -90,6 +90,10 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
90
90
|
const [selected, setSelected] = (0, react_1.useState)(null);
|
|
91
91
|
const [selectedLogs, setSelectedLogs] = (0, react_1.useState)(new Set());
|
|
92
92
|
const [search, setSearch] = (0, react_1.useState)('');
|
|
93
|
+
const [searchScope, setSearchScope] = (0, react_1.useState)('all');
|
|
94
|
+
const [isRegexSearch, setIsRegexSearch] = (0, react_1.useState)(false);
|
|
95
|
+
const [isCaseSensitive, setIsCaseSensitive] = (0, react_1.useState)(false);
|
|
96
|
+
const [quickFilter, setQuickFilter] = (0, react_1.useState)('all');
|
|
93
97
|
const [detailSearch, setDetailSearch] = (0, react_1.useState)('');
|
|
94
98
|
const [reduxSearch, setReduxSearch] = (0, react_1.useState)('');
|
|
95
99
|
const [selectedReduxSlice, setSelectedReduxSlice] = (0, react_1.useState)(null);
|
|
@@ -1041,7 +1045,40 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
1041
1045
|
}, [selected]);
|
|
1042
1046
|
const filteredLogs = (0, react_1.useMemo)(() => {
|
|
1043
1047
|
let result = logs.filter(log => {
|
|
1044
|
-
//
|
|
1048
|
+
// 1. Quick Filter Check (All, Errors, Success, Slow, GET, POST, GraphQL)
|
|
1049
|
+
if (quickFilter && quickFilter !== 'all') {
|
|
1050
|
+
if (quickFilter === 'errors') {
|
|
1051
|
+
const isErr = log.status === 0 ||
|
|
1052
|
+
log.status == null ||
|
|
1053
|
+
(typeof log.status === 'number' && log.status >= 400);
|
|
1054
|
+
if (!isErr)
|
|
1055
|
+
return false;
|
|
1056
|
+
}
|
|
1057
|
+
else if (quickFilter === 'success') {
|
|
1058
|
+
const isSuccess = typeof log.status === 'number' &&
|
|
1059
|
+
log.status >= 200 &&
|
|
1060
|
+
log.status < 400;
|
|
1061
|
+
if (!isSuccess)
|
|
1062
|
+
return false;
|
|
1063
|
+
}
|
|
1064
|
+
else if (quickFilter === 'slow') {
|
|
1065
|
+
if ((log.duration || 0) < 500)
|
|
1066
|
+
return false;
|
|
1067
|
+
}
|
|
1068
|
+
else if (quickFilter === 'graphql') {
|
|
1069
|
+
const isGql = (log.url || '').toLowerCase().includes('graphql') ||
|
|
1070
|
+
(log.client || '').toLowerCase().includes('graphql') ||
|
|
1071
|
+
(log.client || '').toLowerCase().includes('apollo');
|
|
1072
|
+
if (!isGql)
|
|
1073
|
+
return false;
|
|
1074
|
+
}
|
|
1075
|
+
else {
|
|
1076
|
+
if (log.method?.toUpperCase() !== quickFilter.toUpperCase()) {
|
|
1077
|
+
return false;
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
// 2. Status Filter Check (from filters accordion dropdown)
|
|
1045
1082
|
if (statusFilters.size > 0) {
|
|
1046
1083
|
const matched = [...statusFilters].some(f => {
|
|
1047
1084
|
if (f === 'ALL')
|
|
@@ -1057,7 +1094,7 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
1057
1094
|
if (!matched)
|
|
1058
1095
|
return false;
|
|
1059
1096
|
}
|
|
1060
|
-
// Method Filter Check
|
|
1097
|
+
// 3. Method Filter Check (from filters accordion dropdown)
|
|
1061
1098
|
if (methodFilters.size > 0) {
|
|
1062
1099
|
const matchedMethod = [...methodFilters].some(m => {
|
|
1063
1100
|
if (m === 'ALL')
|
|
@@ -1067,10 +1104,14 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
1067
1104
|
if (!matchedMethod)
|
|
1068
1105
|
return false;
|
|
1069
1106
|
}
|
|
1070
|
-
// Advanced Search Query Engine Check
|
|
1107
|
+
// 4. Advanced Search Query Engine Check with Scope, Regex and Case-Sensitivity
|
|
1071
1108
|
if (search && search.trim().length > 0) {
|
|
1072
1109
|
const routePath = logRouteMapRef.current.get(log.id)?.path || '';
|
|
1073
|
-
const isMatch = (0, helpers_1.matchNetworkLogQuery)(log, search, routePath
|
|
1110
|
+
const isMatch = (0, helpers_1.matchNetworkLogQuery)(log, search, routePath, {
|
|
1111
|
+
scope: searchScope,
|
|
1112
|
+
isRegex: isRegexSearch,
|
|
1113
|
+
isCaseSensitive: isCaseSensitive,
|
|
1114
|
+
});
|
|
1074
1115
|
if (!isMatch)
|
|
1075
1116
|
return false;
|
|
1076
1117
|
}
|
|
@@ -1079,9 +1120,7 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
1079
1120
|
if (sortOrder === 'oldest') {
|
|
1080
1121
|
result = [...result].reverse();
|
|
1081
1122
|
}
|
|
1082
|
-
// #9 — collapse consecutive identical requests
|
|
1083
|
-
// status) into one row carrying a ×N counter, unless the user opted in
|
|
1084
|
-
// to seeing every duplicate via Settings → "Show Duplicate Logs".
|
|
1123
|
+
// #9 — collapse consecutive identical requests
|
|
1085
1124
|
if (!showDuplicateLogs) {
|
|
1086
1125
|
const collapsed = [];
|
|
1087
1126
|
for (const log of result) {
|
|
@@ -1105,6 +1144,10 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
1105
1144
|
}, [
|
|
1106
1145
|
logs,
|
|
1107
1146
|
search,
|
|
1147
|
+
searchScope,
|
|
1148
|
+
isRegexSearch,
|
|
1149
|
+
isCaseSensitive,
|
|
1150
|
+
quickFilter,
|
|
1108
1151
|
statusFilters,
|
|
1109
1152
|
methodFilters,
|
|
1110
1153
|
sortOrder,
|
|
@@ -1655,6 +1698,14 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
1655
1698
|
groupedData,
|
|
1656
1699
|
search,
|
|
1657
1700
|
setSearch,
|
|
1701
|
+
searchScope,
|
|
1702
|
+
setSearchScope,
|
|
1703
|
+
isRegexSearch,
|
|
1704
|
+
setIsRegexSearch,
|
|
1705
|
+
isCaseSensitive,
|
|
1706
|
+
setIsCaseSensitive,
|
|
1707
|
+
quickFilter,
|
|
1708
|
+
setQuickFilter,
|
|
1658
1709
|
statusFilters,
|
|
1659
1710
|
setStatusFilters,
|
|
1660
1711
|
methodFilters,
|
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { ViewStyle } from 'react-native';
|
|
3
3
|
import { Animated, PanResponderInstance } from 'react-native';
|
|
4
4
|
import type { ActiveTab, BreadcrumbType, CrashType, GroupedListItem, LocalFilter, LogFilter, Method, SettingsPage, SettingsSubTab, SortOrder, StatusFilter } from './index';
|
|
5
|
+
export type SearchScope = 'all' | 'url' | 'reqBody' | 'resBody' | 'headers';
|
|
5
6
|
export interface ParsedStackFrame {
|
|
6
7
|
method: string;
|
|
7
8
|
file: string;
|
|
@@ -214,6 +215,14 @@ export interface InspectorContextValue {
|
|
|
214
215
|
groupedData: GroupedListItem[];
|
|
215
216
|
search: string;
|
|
216
217
|
setSearch: React.Dispatch<React.SetStateAction<string>>;
|
|
218
|
+
searchScope: SearchScope;
|
|
219
|
+
setSearchScope: React.Dispatch<React.SetStateAction<SearchScope>>;
|
|
220
|
+
isRegexSearch: boolean;
|
|
221
|
+
setIsRegexSearch: React.Dispatch<React.SetStateAction<boolean>>;
|
|
222
|
+
isCaseSensitive: boolean;
|
|
223
|
+
setIsCaseSensitive: React.Dispatch<React.SetStateAction<boolean>>;
|
|
224
|
+
quickFilter: string;
|
|
225
|
+
setQuickFilter: React.Dispatch<React.SetStateAction<string>>;
|
|
217
226
|
statusFilters: Set<StatusFilter>;
|
|
218
227
|
setStatusFilters: React.Dispatch<React.SetStateAction<Set<StatusFilter>>>;
|
|
219
228
|
methodFilters: Set<Method>;
|
|
@@ -11,9 +11,11 @@ import { METHOD_COLORS } from '../../constants';
|
|
|
11
11
|
import { LIB_VERSION } from '../../constants';
|
|
12
12
|
import { getStatusColor, getAppName, formatTime, getSize } from '../../helpers';
|
|
13
13
|
import { getTelemetryConsentStatus } from '../../helpers/telemetry';
|
|
14
|
+
import { UpdateAvailableModal } from './UpdateAvailableModal';
|
|
14
15
|
import { WhiteBackNavigation, TrashIcon, SettingsIcon, CloseWhite, ClockIcon, SizeIcon, AppleIcon, AndroidIcon, NpmIcon, ResetIcon, } from '../NetworkIcons';
|
|
15
16
|
const InspectorHeader = React.memo(() => {
|
|
16
17
|
const { modalHeightPercent, appIcon, selected, setSelected, selectedEvent, setSelectedEvent, selectedLog, setSelectedLog, selectedReduxSlice, setSelectedReduxSlice, selectedReduxAction, setSelectedReduxAction, reduxState, reduxLastActionMap, showHeaderInfo, setShowHeaderInfo, updateAvailable, latestNpmVersion, clearAnim, activePulseAnim, unreadPulseAnim, runClearAllWithAnimation, settingsPage, setSettingsPage, resetToDefaults, closeModal, detailTitle, activeTab, environment, visible, selectedCrash, setSelectedCrash, } = useInspector();
|
|
18
|
+
const [showUpdateModal, setShowUpdateModal] = React.useState(false);
|
|
17
19
|
const [isTelemetryActive, setIsTelemetryActive] = React.useState(false);
|
|
18
20
|
const telemetryPulseAnim = React.useRef(new Animated.Value(1)).current;
|
|
19
21
|
React.useEffect(() => {
|
|
@@ -77,7 +79,8 @@ const InspectorHeader = React.memo(() => {
|
|
|
77
79
|
const isDetailView = (activeTab === 'apis' && selected != null) ||
|
|
78
80
|
(activeTab === 'analytics' && selectedEvent != null) ||
|
|
79
81
|
(activeTab === 'logs' && selectedLog != null) ||
|
|
80
|
-
(activeTab === 'redux' &&
|
|
82
|
+
(activeTab === 'redux' &&
|
|
83
|
+
(selectedReduxSlice != null || selectedReduxAction != null)) ||
|
|
81
84
|
(activeTab === 'crash' && selectedCrash != null);
|
|
82
85
|
const isSettingsView = settingsPage !== null;
|
|
83
86
|
const isAnySelected = isDetailView || isSettingsView;
|
|
@@ -102,7 +105,8 @@ const InspectorHeader = React.memo(() => {
|
|
|
102
105
|
}
|
|
103
106
|
}, [settingsPage]);
|
|
104
107
|
const headerTopPadding = Platform.OS === 'ios' && modalHeightPercent >= 95 ? 44 : 0;
|
|
105
|
-
return (
|
|
108
|
+
return (<>
|
|
109
|
+
<LinearGradient colors={['#4F46E5', '#7C3AED']} start={{ x: 0, y: 0 }} end={{ x: 1, y: 1 }} style={styles.headerGradient}>
|
|
106
110
|
<View style={{ paddingTop: headerTopPadding, width: '100%' }}>
|
|
107
111
|
<View style={styles.header}>
|
|
108
112
|
<View style={[
|
|
@@ -203,7 +207,12 @@ const InspectorHeader = React.memo(() => {
|
|
|
203
207
|
}}>
|
|
204
208
|
<AppHeaderLogo size={46} customIcon={appIcon}/>
|
|
205
209
|
<View style={{ gap: 2.5, flex: 1, minWidth: 0 }}>
|
|
206
|
-
<View style={{
|
|
210
|
+
<View style={{
|
|
211
|
+
flexDirection: 'row',
|
|
212
|
+
alignItems: 'center',
|
|
213
|
+
gap: 6,
|
|
214
|
+
minWidth: 0,
|
|
215
|
+
}}>
|
|
207
216
|
<Text style={[styles.headerTitle, { flexShrink: 1 }]} numberOfLines={1} ellipsizeMode="tail">
|
|
208
217
|
{getAppName()}
|
|
209
218
|
</Text>
|
|
@@ -217,34 +226,41 @@ const InspectorHeader = React.memo(() => {
|
|
|
217
226
|
marginBottom: 0,
|
|
218
227
|
},
|
|
219
228
|
]}>
|
|
220
|
-
<Text style={[
|
|
221
|
-
styles.envBadgeText,
|
|
222
|
-
{ color: envConfig.text },
|
|
223
|
-
]}>
|
|
229
|
+
<Text style={[styles.envBadgeText, { color: envConfig.text }]}>
|
|
224
230
|
{envConfig.label}
|
|
225
231
|
</Text>
|
|
226
232
|
</View>
|
|
227
|
-
{updateAvailable && (<Pressable hitSlop={10} onPress={() =>
|
|
228
|
-
|
|
229
|
-
{
|
|
230
|
-
text: 'View on NPM',
|
|
231
|
-
onPress: () => Linking.openURL('https://www.npmjs.com/package/react-native-inapp-inspector').catch(() => { }),
|
|
232
|
-
},
|
|
233
|
-
])} style={{
|
|
233
|
+
{updateAvailable && (<Pressable hitSlop={10} onPress={() => setShowUpdateModal(true)} style={{
|
|
234
|
+
flexDirection: 'row',
|
|
234
235
|
alignItems: 'center',
|
|
235
|
-
|
|
236
|
+
backgroundColor: '#F59E0B',
|
|
237
|
+
borderRadius: 5,
|
|
238
|
+
paddingHorizontal: 5.5,
|
|
239
|
+
paddingVertical: 1.5,
|
|
240
|
+
gap: 3.5,
|
|
241
|
+
shadowColor: '#F59E0B',
|
|
242
|
+
shadowOffset: { width: 0, height: 1.5 },
|
|
243
|
+
shadowOpacity: 0.35,
|
|
244
|
+
shadowRadius: 3,
|
|
245
|
+
elevation: 3,
|
|
236
246
|
flexShrink: 0,
|
|
237
247
|
}}>
|
|
238
248
|
<Animated.View style={{
|
|
239
|
-
width:
|
|
240
|
-
height:
|
|
241
|
-
borderRadius:
|
|
242
|
-
backgroundColor:
|
|
243
|
-
borderWidth: 1,
|
|
244
|
-
borderColor: `${AppColors.white}E6`,
|
|
249
|
+
width: 5,
|
|
250
|
+
height: 5,
|
|
251
|
+
borderRadius: 2.5,
|
|
252
|
+
backgroundColor: '#FFFFFF',
|
|
245
253
|
opacity: activePulseAnim,
|
|
246
254
|
transform: [{ scale: unreadPulseAnim }],
|
|
247
255
|
}}/>
|
|
256
|
+
<Text style={{
|
|
257
|
+
fontFamily: AppFonts.interBold,
|
|
258
|
+
fontSize: 9,
|
|
259
|
+
color: '#FFFFFF',
|
|
260
|
+
letterSpacing: 0.3,
|
|
261
|
+
}}>
|
|
262
|
+
UPDATE ⚡
|
|
263
|
+
</Text>
|
|
248
264
|
</Pressable>)}
|
|
249
265
|
</View>
|
|
250
266
|
|
|
@@ -280,7 +296,14 @@ const InspectorHeader = React.memo(() => {
|
|
|
280
296
|
</Text>
|
|
281
297
|
</View>
|
|
282
298
|
|
|
283
|
-
<Pressable onPress={() =>
|
|
299
|
+
<Pressable onPress={() => {
|
|
300
|
+
if (updateAvailable) {
|
|
301
|
+
setShowUpdateModal(true);
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
Linking.openURL('https://www.npmjs.com/package/react-native-inapp-inspector').catch(() => { });
|
|
305
|
+
}
|
|
306
|
+
}} style={{
|
|
284
307
|
backgroundColor: '#FFFFFF',
|
|
285
308
|
borderRadius: 5,
|
|
286
309
|
paddingHorizontal: 6,
|
|
@@ -304,6 +327,13 @@ const InspectorHeader = React.memo(() => {
|
|
|
304
327
|
}} numberOfLines={1}>
|
|
305
328
|
v{LIB_VERSION}
|
|
306
329
|
</Text>
|
|
330
|
+
{updateAvailable && (<Text style={{
|
|
331
|
+
fontFamily: AppFonts.interBold,
|
|
332
|
+
fontSize: 9,
|
|
333
|
+
color: '#F59E0B',
|
|
334
|
+
}}>
|
|
335
|
+
↑
|
|
336
|
+
</Text>)}
|
|
307
337
|
</Pressable>
|
|
308
338
|
|
|
309
339
|
{isTelemetryActive && (<Pressable onPress={() => Alert.alert('Anonymous Telemetry Active', 'Anonymous diagnostics (such as React Native version, JavaScript engine, and device model) are currently enabled to help improve library tooling.\n\nNo user data or network payloads are captured. You can toggle this anytime in Settings.', [{ text: 'Got it' }])} style={{
|
|
@@ -444,9 +474,7 @@ const InspectorHeader = React.memo(() => {
|
|
|
444
474
|
},
|
|
445
475
|
]}>
|
|
446
476
|
<Text style={styles.headerMethodText}>
|
|
447
|
-
{selectedEvent.source === 'firebase'
|
|
448
|
-
? 'FB'
|
|
449
|
-
: 'MAN'}
|
|
477
|
+
{selectedEvent.source === 'firebase' ? 'FB' : 'MAN'}
|
|
450
478
|
</Text>
|
|
451
479
|
</View>
|
|
452
480
|
<Text style={styles.headerDetailTitle} numberOfLines={1} ellipsizeMode="middle">
|
|
@@ -489,9 +517,7 @@ const InspectorHeader = React.memo(() => {
|
|
|
489
517
|
</View>
|
|
490
518
|
<Text style={styles.headerDetailTitle} numberOfLines={1} ellipsizeMode="middle">
|
|
491
519
|
console.
|
|
492
|
-
{
|
|
493
|
-
selectedLog.type ||
|
|
494
|
-
'log'}
|
|
520
|
+
{selectedLog.sourceMethod || selectedLog.type || 'log'}
|
|
495
521
|
</Text>
|
|
496
522
|
</View>
|
|
497
523
|
<View style={styles.headerDetailSubRow}>
|
|
@@ -504,10 +530,10 @@ const InspectorHeader = React.memo(() => {
|
|
|
504
530
|
borderRadius: 20,
|
|
505
531
|
backgroundColor: `${AppColors.white}29`,
|
|
506
532
|
}}>
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
533
|
+
<ClockIcon color={AppColors.white} size={11}/>
|
|
534
|
+
<Text style={styles.headerSubTitle}>
|
|
535
|
+
{formatTime(selectedLog.timestamp)}
|
|
536
|
+
</Text>
|
|
511
537
|
</View>
|
|
512
538
|
</View>
|
|
513
539
|
</View>) : activeTab === 'redux' && selectedReduxSlice != null ? ((() => {
|
|
@@ -527,9 +553,7 @@ const InspectorHeader = React.memo(() => {
|
|
|
527
553
|
backgroundColor: `${AppColors.purple}4D`,
|
|
528
554
|
},
|
|
529
555
|
]}>
|
|
530
|
-
<Text style={styles.headerMethodText}>
|
|
531
|
-
SLICE
|
|
532
|
-
</Text>
|
|
556
|
+
<Text style={styles.headerMethodText}>SLICE</Text>
|
|
533
557
|
</View>
|
|
534
558
|
<Text style={styles.headerDetailTitle} numberOfLines={1} ellipsizeMode="middle">
|
|
535
559
|
{selectedReduxSlice}
|
|
@@ -540,20 +564,26 @@ const InspectorHeader = React.memo(() => {
|
|
|
540
564
|
styles.headerStatusDot,
|
|
541
565
|
{ backgroundColor: AppColors.liveGreen },
|
|
542
566
|
]}/>
|
|
543
|
-
<Text style={styles.headerSubTitle}>
|
|
544
|
-
|
|
567
|
+
<Text style={styles.headerSubTitle}>Live</Text>
|
|
568
|
+
<Text style={[styles.headerSubTitle, { opacity: 0.6 }]}>
|
|
569
|
+
•
|
|
545
570
|
</Text>
|
|
546
|
-
<Text style={[styles.headerSubTitle, { opacity: 0.6 }]}>•</Text>
|
|
547
571
|
<Text style={styles.headerSubTitle}>
|
|
548
572
|
{keyCount} keys
|
|
549
573
|
</Text>
|
|
550
|
-
<Text style={[styles.headerSubTitle, { opacity: 0.6 }]}
|
|
551
|
-
|
|
552
|
-
{sliceSize}
|
|
574
|
+
<Text style={[styles.headerSubTitle, { opacity: 0.6 }]}>
|
|
575
|
+
•
|
|
553
576
|
</Text>
|
|
577
|
+
<Text style={styles.headerSubTitle}>{sliceSize}</Text>
|
|
554
578
|
{lastAction?.timestamp && (<>
|
|
555
|
-
<Text style={[styles.headerSubTitle, { opacity: 0.6 }]}
|
|
556
|
-
|
|
579
|
+
<Text style={[styles.headerSubTitle, { opacity: 0.6 }]}>
|
|
580
|
+
•
|
|
581
|
+
</Text>
|
|
582
|
+
<View style={{
|
|
583
|
+
flexDirection: 'row',
|
|
584
|
+
alignItems: 'center',
|
|
585
|
+
gap: 3,
|
|
586
|
+
}}>
|
|
557
587
|
<ClockIcon color={AppColors.white} size={10}/>
|
|
558
588
|
<Text style={styles.headerSubTitle}>
|
|
559
589
|
{lastAction.timestamp}
|
|
@@ -570,9 +600,7 @@ const InspectorHeader = React.memo(() => {
|
|
|
570
600
|
backgroundColor: `${AppColors.brandPurple}4D`,
|
|
571
601
|
},
|
|
572
602
|
]}>
|
|
573
|
-
<Text style={styles.headerMethodText}>
|
|
574
|
-
ACTION
|
|
575
|
-
</Text>
|
|
603
|
+
<Text style={styles.headerMethodText}>ACTION</Text>
|
|
576
604
|
</View>
|
|
577
605
|
<Text style={styles.headerDetailTitle} numberOfLines={1} ellipsizeMode="middle">
|
|
578
606
|
{selectedReduxAction.type}
|
|
@@ -598,7 +626,9 @@ const InspectorHeader = React.memo(() => {
|
|
|
598
626
|
},
|
|
599
627
|
]}>
|
|
600
628
|
<Text style={styles.headerMethodText}>
|
|
601
|
-
{selectedCrash.isFatal
|
|
629
|
+
{selectedCrash.isFatal
|
|
630
|
+
? 'FATAL'
|
|
631
|
+
: selectedCrash.type.toUpperCase()}
|
|
602
632
|
</Text>
|
|
603
633
|
</View>
|
|
604
634
|
<Text style={styles.headerDetailTitle} numberOfLines={1} ellipsizeMode="middle">
|
|
@@ -615,10 +645,13 @@ const InspectorHeader = React.memo(() => {
|
|
|
615
645
|
},
|
|
616
646
|
]}/>
|
|
617
647
|
<Text style={styles.headerSubTitle}>
|
|
618
|
-
{selectedCrash.timeStr ||
|
|
648
|
+
{selectedCrash.timeStr ||
|
|
649
|
+
new Date(selectedCrash.timestamp).toLocaleTimeString()}
|
|
619
650
|
</Text>
|
|
620
651
|
{selectedCrash.deviceInfo?.platform && (<>
|
|
621
|
-
<Text style={[styles.headerSubTitle, { opacity: 0.6 }]}
|
|
652
|
+
<Text style={[styles.headerSubTitle, { opacity: 0.6 }]}>
|
|
653
|
+
•
|
|
654
|
+
</Text>
|
|
622
655
|
<Text style={styles.headerSubTitle}>
|
|
623
656
|
{selectedCrash.deviceInfo.platform.toUpperCase()}
|
|
624
657
|
</Text>
|
|
@@ -690,6 +723,10 @@ const InspectorHeader = React.memo(() => {
|
|
|
690
723
|
</View>
|
|
691
724
|
</View>
|
|
692
725
|
</View>
|
|
693
|
-
</LinearGradient>
|
|
726
|
+
</LinearGradient>
|
|
727
|
+
|
|
728
|
+
{/* Dedicated Update Available Details Modal */}
|
|
729
|
+
<UpdateAvailableModal visible={showUpdateModal} latestVersion={latestNpmVersion} onClose={() => setShowUpdateModal(false)}/>
|
|
730
|
+
</>);
|
|
694
731
|
});
|
|
695
732
|
export default InspectorHeader;
|
|
@@ -68,6 +68,7 @@ const MainScreen = () => {
|
|
|
68
68
|
return (<>
|
|
69
69
|
{(Platform.OS === 'ios' || Platform.OS === 'android') &&
|
|
70
70
|
isEnabled &&
|
|
71
|
+
!visible &&
|
|
71
72
|
!useNativeFab && <FabLauncher />}
|
|
72
73
|
<Modal visible={visible} animationType={modalAnimationType} transparent statusBarTranslucent={true}>
|
|
73
74
|
{visible && (<ErrorBoundary onClose={closeModal}>
|