react-native-inapp-inspector 2.2.9 → 2.3.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/dist/commonjs/components/AppHeaderLogo.js +45 -12
- package/dist/commonjs/components/BrandSquareIcon.js +92 -49
- package/dist/commonjs/components/EmptyState.d.ts +7 -2
- package/dist/commonjs/components/EmptyState.js +11 -5
- package/dist/commonjs/components/Inspector/AnalyticsTab.js +29 -18
- package/dist/commonjs/components/Inspector/ConsoleTab.js +6 -1
- package/dist/commonjs/components/Inspector/CrashDetail.js +43 -9
- package/dist/commonjs/components/Inspector/CrashTab.js +34 -3
- package/dist/commonjs/components/Inspector/DeviceInfoTab.js +80 -16
- package/dist/commonjs/components/Inspector/InspectorHeader.js +16 -3
- package/dist/commonjs/components/Inspector/MainScreen.js +7 -11
- package/dist/commonjs/components/Inspector/NetworkDetail.js +3 -2
- package/dist/commonjs/components/Inspector/NetworkTab.js +103 -4
- package/dist/commonjs/components/Inspector/ReduxTab.js +19 -3
- package/dist/commonjs/components/Inspector/SettingsPanel.js +4 -4
- package/dist/commonjs/components/Inspector/StorageTab.js +123 -92
- package/dist/commonjs/components/JsonViewer.js +2 -0
- package/dist/commonjs/components/MetaAccordion.js +15 -3
- package/dist/commonjs/components/SkeletonPlaceholder.d.ts +6 -0
- package/dist/commonjs/components/SkeletonPlaceholder.js +208 -0
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/networkLogger.d.ts +3 -0
- package/dist/commonjs/customHooks/networkLogger.js +10 -1
- package/dist/commonjs/customHooks/storageInspector.d.ts +2 -2
- package/dist/commonjs/customHooks/storageInspector.js +17 -13
- package/dist/commonjs/helpers/index.d.ts +6 -0
- package/dist/commonjs/helpers/index.js +196 -6
- package/dist/commonjs/helpers/searchQueryParser.js +62 -20
- package/dist/commonjs/i18n/index.d.ts +13 -0
- package/dist/commonjs/i18n/index.js +35 -2
- package/dist/commonjs/index.d.ts +3 -0
- package/dist/commonjs/index.js +108 -35
- package/dist/commonjs/styles/AppColors.d.ts +4 -0
- package/dist/commonjs/styles/AppColors.js +11 -1
- package/dist/commonjs/styles/AppFonts.d.ts +11 -0
- package/dist/commonjs/styles/AppFonts.js +11 -1
- package/dist/commonjs/types/interfaces.d.ts +2 -2
- package/dist/esm/components/AppHeaderLogo.js +45 -12
- package/dist/esm/components/BrandSquareIcon.js +92 -49
- package/dist/esm/components/EmptyState.d.ts +7 -2
- package/dist/esm/components/EmptyState.js +11 -5
- package/dist/esm/components/Inspector/AnalyticsTab.js +30 -19
- package/dist/esm/components/Inspector/ConsoleTab.js +6 -1
- package/dist/esm/components/Inspector/CrashDetail.js +43 -9
- package/dist/esm/components/Inspector/CrashTab.js +34 -3
- package/dist/esm/components/Inspector/DeviceInfoTab.js +80 -16
- package/dist/esm/components/Inspector/InspectorHeader.js +17 -4
- package/dist/esm/components/Inspector/MainScreen.js +8 -12
- package/dist/esm/components/Inspector/NetworkDetail.js +3 -2
- package/dist/esm/components/Inspector/NetworkTab.js +103 -4
- package/dist/esm/components/Inspector/ReduxTab.js +19 -3
- package/dist/esm/components/Inspector/SettingsPanel.js +4 -4
- package/dist/esm/components/Inspector/StorageTab.js +124 -93
- package/dist/esm/components/JsonViewer.js +2 -0
- package/dist/esm/components/MetaAccordion.js +15 -3
- package/dist/esm/components/SkeletonPlaceholder.d.ts +6 -0
- package/dist/esm/components/SkeletonPlaceholder.js +173 -0
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/networkLogger.d.ts +3 -0
- package/dist/esm/customHooks/networkLogger.js +8 -0
- package/dist/esm/customHooks/storageInspector.d.ts +2 -2
- package/dist/esm/customHooks/storageInspector.js +17 -13
- package/dist/esm/helpers/index.d.ts +6 -0
- package/dist/esm/helpers/index.js +193 -5
- package/dist/esm/helpers/searchQueryParser.js +62 -20
- package/dist/esm/i18n/index.d.ts +13 -0
- package/dist/esm/i18n/index.js +33 -3
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +97 -37
- package/dist/esm/styles/AppColors.d.ts +4 -0
- package/dist/esm/styles/AppColors.js +9 -0
- package/dist/esm/styles/AppFonts.d.ts +11 -0
- package/dist/esm/styles/AppFonts.js +9 -0
- package/dist/esm/types/interfaces.d.ts +2 -2
- package/package.json +1 -1
- package/src/components/AppHeaderLogo.tsx +46 -12
- package/src/components/BrandSquareIcon.tsx +127 -78
- package/src/components/EmptyState.tsx +27 -5
- package/src/components/Inspector/AnalyticsTab.tsx +48 -27
- package/src/components/Inspector/ConsoleTab.tsx +10 -0
- package/src/components/Inspector/CrashDetail.tsx +65 -9
- package/src/components/Inspector/CrashTab.tsx +41 -3
- package/src/components/Inspector/DeviceInfoTab.tsx +87 -16
- package/src/components/Inspector/InspectorHeader.tsx +24 -4
- package/src/components/Inspector/MainScreen.tsx +7 -11
- package/src/components/Inspector/NetworkDetail.tsx +4 -4
- package/src/components/Inspector/NetworkTab.tsx +129 -4
- package/src/components/Inspector/ReduxTab.tsx +26 -8
- package/src/components/Inspector/SettingsPanel.tsx +4 -4
- package/src/components/Inspector/StorageTab.tsx +191 -117
- package/src/components/JsonViewer.tsx +2 -0
- package/src/components/MetaAccordion.tsx +18 -3
- package/src/components/SkeletonPlaceholder.tsx +206 -0
- package/src/constants/version.ts +1 -1
- package/src/customHooks/networkLogger.ts +15 -0
- package/src/customHooks/storageInspector.ts +18 -14
- package/src/helpers/index.ts +213 -5
- package/src/helpers/searchQueryParser.ts +63 -20
- package/src/i18n/index.ts +38 -3
- package/src/index.tsx +124 -37
- package/src/styles/AppColors.ts +9 -0
- package/src/styles/AppFonts.ts +16 -0
- package/src/types/interfaces.ts +2 -2
|
@@ -47,6 +47,92 @@ const NetworkIcons_1 = require("../NetworkIcons");
|
|
|
47
47
|
const storageInspector_1 = require("../../customHooks/storageInspector");
|
|
48
48
|
const helpers_1 = require("../../helpers");
|
|
49
49
|
const toast_1 = require("../../helpers/toast");
|
|
50
|
+
const getTypeBadge = (type) => {
|
|
51
|
+
switch (type) {
|
|
52
|
+
case 'json':
|
|
53
|
+
return { label: 'JSON', color: AppColors_1.AppColors.purple, bg: `${AppColors_1.AppColors.purple}16` };
|
|
54
|
+
case 'number':
|
|
55
|
+
return { label: 'NUM', color: AppColors_1.AppColors.warningIconGold, bg: `${AppColors_1.AppColors.warningIconGold}16` };
|
|
56
|
+
case 'boolean':
|
|
57
|
+
return { label: 'BOOL', color: AppColors_1.AppColors.emerald500, bg: `${AppColors_1.AppColors.emerald500}16` };
|
|
58
|
+
case 'null':
|
|
59
|
+
return { label: 'NULL', color: AppColors_1.AppColors.grayTextWeak, bg: `${AppColors_1.AppColors.grayTextWeak}16` };
|
|
60
|
+
default:
|
|
61
|
+
return { label: 'STR', color: AppColors_1.AppColors.blue500, bg: `${AppColors_1.AppColors.blue500}16` };
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const StorageEntryCard = react_1.default.memo(function StorageEntryCard({ entry, isExpanded, onToggleExpand, onCopy, onEdit, onDelete, badge, }) {
|
|
65
|
+
const formattedBytes = (0, react_1.useMemo)(() => {
|
|
66
|
+
return entry.byteSize < 1024
|
|
67
|
+
? `${entry.byteSize} B`
|
|
68
|
+
: `${(entry.byteSize / 1024).toFixed(1)} KB`;
|
|
69
|
+
}, [entry.byteSize]);
|
|
70
|
+
// Lazy compute displayed value to avoid layout thrashing on large JSON strings
|
|
71
|
+
const displayValue = (0, react_1.useMemo)(() => {
|
|
72
|
+
if (!isExpanded) {
|
|
73
|
+
if (entry.value.length > 250) {
|
|
74
|
+
return entry.value.slice(0, 250) + '...';
|
|
75
|
+
}
|
|
76
|
+
return entry.value;
|
|
77
|
+
}
|
|
78
|
+
if (entry.type === 'json') {
|
|
79
|
+
try {
|
|
80
|
+
const parsed = entry.parsedValue ?? JSON.parse(entry.value);
|
|
81
|
+
return JSON.stringify(parsed, null, 2);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return entry.value;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return entry.value;
|
|
88
|
+
}, [isExpanded, entry.value, entry.type, entry.parsedValue]);
|
|
89
|
+
return (<react_native_1.View style={styles.entryCard}>
|
|
90
|
+
{/* Entry Header: Key name, Type Badge, Size, Actions */}
|
|
91
|
+
<react_native_1.View style={styles.entryHeader}>
|
|
92
|
+
<react_native_1.View style={{ flex: 1, marginRight: 8 }}>
|
|
93
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
|
|
94
|
+
<react_native_1.Text style={styles.entryKey} numberOfLines={1} selectable>
|
|
95
|
+
{entry.key}
|
|
96
|
+
</react_native_1.Text>
|
|
97
|
+
<react_native_1.View style={[
|
|
98
|
+
styles.typeBadge,
|
|
99
|
+
{ backgroundColor: badge.bg, borderColor: `${badge.color}33` },
|
|
100
|
+
]}>
|
|
101
|
+
<react_native_1.Text style={[styles.typeBadgeText, { color: badge.color }]}>
|
|
102
|
+
{badge.label}
|
|
103
|
+
</react_native_1.Text>
|
|
104
|
+
</react_native_1.View>
|
|
105
|
+
<react_native_1.Text style={styles.sizeText}>{formattedBytes}</react_native_1.Text>
|
|
106
|
+
</react_native_1.View>
|
|
107
|
+
</react_native_1.View>
|
|
108
|
+
|
|
109
|
+
{/* Actions: Copy, Edit, Delete */}
|
|
110
|
+
<react_native_1.View style={styles.entryActions}>
|
|
111
|
+
<TouchableScale_1.default hitSlop={6} onPress={() => onCopy(entry)} style={styles.entryActionBtn}>
|
|
112
|
+
<NetworkIcons_1.CopyIcon size={12} color={AppColors_1.AppColors.grayText}/>
|
|
113
|
+
</TouchableScale_1.default>
|
|
114
|
+
|
|
115
|
+
<TouchableScale_1.default hitSlop={6} onPress={() => onEdit(entry)} style={styles.entryActionBtn}>
|
|
116
|
+
<NetworkIcons_1.PencilIcon size={12} color={AppColors_1.AppColors.purple}/>
|
|
117
|
+
</TouchableScale_1.default>
|
|
118
|
+
|
|
119
|
+
<TouchableScale_1.default hitSlop={6} onPress={() => onDelete(entry.key)} style={[styles.entryActionBtn, { backgroundColor: `${AppColors_1.AppColors.errorColor}12` }]}>
|
|
120
|
+
<NetworkIcons_1.TrashIcon size={12} color={AppColors_1.AppColors.errorColor}/>
|
|
121
|
+
</TouchableScale_1.default>
|
|
122
|
+
</react_native_1.View>
|
|
123
|
+
</react_native_1.View>
|
|
124
|
+
|
|
125
|
+
{/* Entry Value Preview / Viewer */}
|
|
126
|
+
<TouchableScale_1.default onPress={() => onToggleExpand(entry.key)} style={styles.valuePreviewBox}>
|
|
127
|
+
<react_native_1.Text style={styles.valuePreviewText} numberOfLines={isExpanded ? undefined : 3} selectable={isExpanded}>
|
|
128
|
+
{displayValue}
|
|
129
|
+
</react_native_1.Text>
|
|
130
|
+
{entry.value.length > 80 && (<react_native_1.Text style={styles.expandHint}>
|
|
131
|
+
{isExpanded ? '▲ Collapse' : '▼ Expand'}
|
|
132
|
+
</react_native_1.Text>)}
|
|
133
|
+
</TouchableScale_1.default>
|
|
134
|
+
</react_native_1.View>);
|
|
135
|
+
});
|
|
50
136
|
exports.StorageTab = react_1.default.memo(() => {
|
|
51
137
|
const { t } = (0, i18n_1.useTranslation)();
|
|
52
138
|
const [activeDriver, setActiveDriver] = (0, react_1.useState)('asyncStorage');
|
|
@@ -205,20 +291,11 @@ exports.StorageTab = react_1.default.memo(() => {
|
|
|
205
291
|
return `${(totalBytes / 1024).toFixed(1)} KB`;
|
|
206
292
|
return `${(totalBytes / (1024 * 1024)).toFixed(2)} MB`;
|
|
207
293
|
}, [totalBytes]);
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
return { label: 'NUM', color: AppColors_1.AppColors.warningIconGold, bg: `${AppColors_1.AppColors.warningIconGold}16` };
|
|
214
|
-
case 'boolean':
|
|
215
|
-
return { label: 'BOOL', color: AppColors_1.AppColors.emerald500, bg: `${AppColors_1.AppColors.emerald500}16` };
|
|
216
|
-
case 'null':
|
|
217
|
-
return { label: 'NULL', color: AppColors_1.AppColors.grayTextWeak, bg: `${AppColors_1.AppColors.grayTextWeak}16` };
|
|
218
|
-
default:
|
|
219
|
-
return { label: 'STR', color: AppColors_1.AppColors.blue500, bg: `${AppColors_1.AppColors.blue500}16` };
|
|
220
|
-
}
|
|
221
|
-
};
|
|
294
|
+
const handleCopyEntry = (0, react_1.useCallback)((entry) => {
|
|
295
|
+
(0, helpers_1.copyToClipboard)(entry.value, entry.key);
|
|
296
|
+
(0, toast_1.showToast)(`Copied value of "${entry.key}"`);
|
|
297
|
+
}, []);
|
|
298
|
+
const renderItem = (0, react_1.useCallback)(({ item }) => (<StorageEntryCard entry={item} isExpanded={Boolean(expandedKeys[item.key])} onToggleExpand={toggleExpand} onCopy={handleCopyEntry} onEdit={handleOpenEdit} onDelete={handleDeleteKey} badge={getTypeBadge(item.type)}/>), [expandedKeys, handleCopyEntry]);
|
|
222
299
|
const isConnected = activeDriver === 'asyncStorage'
|
|
223
300
|
? (0, storageInspector_1.isAsyncStorageConnected)()
|
|
224
301
|
: (0, storageInspector_1.isMMKVConnected)();
|
|
@@ -284,9 +361,25 @@ exports.StorageTab = react_1.default.memo(() => {
|
|
|
284
361
|
<react_native_1.View style={styles.searchBar}>
|
|
285
362
|
<NetworkIcons_1.SearchIcon size={14} color={AppColors_1.AppColors.grayTextWeak}/>
|
|
286
363
|
<react_native_1.TextInput value={search} onChangeText={setSearch} placeholder={`Search ${entries.length} keys & values...`} placeholderTextColor={AppColors_1.AppColors.grayTextWeak} style={styles.searchInput} clearButtonMode="while-editing"/>
|
|
287
|
-
{search.length > 0 && (<
|
|
288
|
-
<
|
|
289
|
-
|
|
364
|
+
{search.length > 0 && (<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 4 }}>
|
|
365
|
+
<react_native_1.View style={{
|
|
366
|
+
backgroundColor: `${AppColors_1.AppColors.purple}20`,
|
|
367
|
+
borderRadius: 10,
|
|
368
|
+
paddingHorizontal: 6,
|
|
369
|
+
paddingVertical: 1.5,
|
|
370
|
+
}}>
|
|
371
|
+
<react_native_1.Text style={{
|
|
372
|
+
color: AppColors_1.AppColors.purple,
|
|
373
|
+
fontSize: 9.5,
|
|
374
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
375
|
+
}}>
|
|
376
|
+
{filteredEntries.length}
|
|
377
|
+
</react_native_1.Text>
|
|
378
|
+
</react_native_1.View>
|
|
379
|
+
<TouchableScale_1.default onPress={() => setSearch('')} hitSlop={8}>
|
|
380
|
+
<NetworkIcons_1.ClearIcon size={13} color={AppColors_1.AppColors.grayTextWeak}/>
|
|
381
|
+
</TouchableScale_1.default>
|
|
382
|
+
</react_native_1.View>)}
|
|
290
383
|
</react_native_1.View>
|
|
291
384
|
|
|
292
385
|
{/* Action Buttons: Add Key & Refresh */}
|
|
@@ -318,81 +411,19 @@ exports.StorageTab = react_1.default.memo(() => {
|
|
|
318
411
|
{isLoading ? (<react_native_1.View style={styles.loadingContainer}>
|
|
319
412
|
<react_native_1.ActivityIndicator size="small" color={AppColors_1.AppColors.purple}/>
|
|
320
413
|
<react_native_1.Text style={styles.loadingText}>Loading storage entries...</react_native_1.Text>
|
|
321
|
-
</react_native_1.View>) : filteredEntries.
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
{filteredEntries.map(entry => {
|
|
335
|
-
const isExpanded = Boolean(expandedKeys[entry.key]);
|
|
336
|
-
const badge = getTypeBadge(entry.type);
|
|
337
|
-
const formattedBytes = entry.byteSize < 1024
|
|
338
|
-
? `${entry.byteSize} B`
|
|
339
|
-
: `${(entry.byteSize / 1024).toFixed(1)} KB`;
|
|
340
|
-
return (<react_native_1.View key={entry.key} style={styles.entryCard}>
|
|
341
|
-
{/* Entry Header: Key name, Type Badge, Size, Actions */}
|
|
342
|
-
<react_native_1.View style={styles.entryHeader}>
|
|
343
|
-
<react_native_1.View style={{ flex: 1, marginRight: 8 }}>
|
|
344
|
-
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
|
|
345
|
-
<react_native_1.Text style={styles.entryKey} numberOfLines={1} selectable>
|
|
346
|
-
{entry.key}
|
|
347
|
-
</react_native_1.Text>
|
|
348
|
-
<react_native_1.View style={[
|
|
349
|
-
styles.typeBadge,
|
|
350
|
-
{ backgroundColor: badge.bg, borderColor: `${badge.color}33` },
|
|
351
|
-
]}>
|
|
352
|
-
<react_native_1.Text style={[styles.typeBadgeText, { color: badge.color }]}>
|
|
353
|
-
{badge.label}
|
|
354
|
-
</react_native_1.Text>
|
|
355
|
-
</react_native_1.View>
|
|
356
|
-
<react_native_1.Text style={styles.sizeText}>{formattedBytes}</react_native_1.Text>
|
|
357
|
-
</react_native_1.View>
|
|
358
|
-
</react_native_1.View>
|
|
359
|
-
|
|
360
|
-
{/* Actions: Copy, Edit, Delete */}
|
|
361
|
-
<react_native_1.View style={styles.entryActions}>
|
|
362
|
-
<TouchableScale_1.default hitSlop={6} onPress={() => {
|
|
363
|
-
(0, helpers_1.copyToClipboard)(entry.value, entry.key);
|
|
364
|
-
(0, toast_1.showToast)(`Copied value of "${entry.key}"`);
|
|
365
|
-
}} style={styles.entryActionBtn}>
|
|
366
|
-
<NetworkIcons_1.CopyIcon size={12} color={AppColors_1.AppColors.grayText}/>
|
|
367
|
-
</TouchableScale_1.default>
|
|
368
|
-
|
|
369
|
-
<TouchableScale_1.default hitSlop={6} onPress={() => handleOpenEdit(entry)} style={styles.entryActionBtn}>
|
|
370
|
-
<NetworkIcons_1.PencilIcon size={12} color={AppColors_1.AppColors.purple}/>
|
|
371
|
-
</TouchableScale_1.default>
|
|
372
|
-
|
|
373
|
-
<TouchableScale_1.default hitSlop={6} onPress={() => handleDeleteKey(entry.key)} style={[styles.entryActionBtn, { backgroundColor: `${AppColors_1.AppColors.errorColor}12` }]}>
|
|
374
|
-
<NetworkIcons_1.TrashIcon size={12} color={AppColors_1.AppColors.errorColor}/>
|
|
375
|
-
</TouchableScale_1.default>
|
|
376
|
-
</react_native_1.View>
|
|
377
|
-
</react_native_1.View>
|
|
378
|
-
|
|
379
|
-
{/* Entry Value Preview / Viewer */}
|
|
380
|
-
<TouchableScale_1.default onPress={() => toggleExpand(entry.key)} style={styles.valuePreviewBox}>
|
|
381
|
-
<react_native_1.Text style={styles.valuePreviewText} numberOfLines={isExpanded ? undefined : 3} selectable>
|
|
382
|
-
{entry.type === 'json' && entry.parsedValue
|
|
383
|
-
? isExpanded
|
|
384
|
-
? JSON.stringify(entry.parsedValue, null, 2)
|
|
385
|
-
: entry.value
|
|
386
|
-
: entry.value}
|
|
387
|
-
</react_native_1.Text>
|
|
388
|
-
{entry.value.length > 80 && (<react_native_1.Text style={styles.expandHint}>
|
|
389
|
-
{isExpanded ? '▲ Collapse' : '▼ Expand'}
|
|
390
|
-
</react_native_1.Text>)}
|
|
391
|
-
</TouchableScale_1.default>
|
|
392
|
-
</react_native_1.View>);
|
|
393
|
-
})}
|
|
394
|
-
<react_native_1.View style={{ height: 60 }}/>
|
|
395
|
-
</react_native_1.ScrollView>)}
|
|
414
|
+
</react_native_1.View>) : (<react_native_1.FlatList data={filteredEntries} keyExtractor={item => item.key} renderItem={renderItem} initialNumToRender={10} maxToRenderPerBatch={10} windowSize={5} removeClippedSubviews={react_native_1.Platform.OS === 'android'} style={styles.scrollArea} contentContainerStyle={styles.scrollContent} showsVerticalScrollIndicator={false} ListEmptyComponent={<react_native_1.View style={styles.emptyContainer}>
|
|
415
|
+
<react_native_1.View style={styles.emptyIconWrap}>
|
|
416
|
+
<NetworkIcons_1.DatabaseIcon size={28} color={AppColors_1.AppColors.grayTextWeak}/>
|
|
417
|
+
</react_native_1.View>
|
|
418
|
+
<react_native_1.Text style={styles.emptyTitle}>
|
|
419
|
+
{search ? 'No matching keys found' : `No ${activeDriver === 'asyncStorage' ? 'AsyncStorage' : 'MMKV'} Keys`}
|
|
420
|
+
</react_native_1.Text>
|
|
421
|
+
<react_native_1.Text style={styles.emptySubtitle}>
|
|
422
|
+
{search
|
|
423
|
+
? 'Try modifying your search query'
|
|
424
|
+
: `Storage is auto-detected. Tap "+ Add" above to create your first ${activeDriver === 'asyncStorage' ? 'AsyncStorage' : 'MMKV'} key!`}
|
|
425
|
+
</react_native_1.Text>
|
|
426
|
+
</react_native_1.View>} ListFooterComponent={<react_native_1.View style={{ height: 60 }}/>}/>)}
|
|
396
427
|
|
|
397
428
|
{/* ── Create / Edit Key Modal ── */}
|
|
398
429
|
<react_native_1.Modal visible={modalVisible} transparent animationType="fade" onRequestClose={() => setModalVisible(false)}>
|
|
@@ -43,6 +43,7 @@ const i18n_1 = require("../i18n");
|
|
|
43
43
|
const TreeNode_1 = __importDefault(require("./TreeNode"));
|
|
44
44
|
const SegmentedTabs_1 = __importDefault(require("./SegmentedTabs"));
|
|
45
45
|
const HighlightText_1 = __importDefault(require("./HighlightText"));
|
|
46
|
+
const CopyButton_1 = __importDefault(require("./CopyButton"));
|
|
46
47
|
const NetworkIcons_1 = require("./NetworkIcons");
|
|
47
48
|
// Styles
|
|
48
49
|
const AppColors_1 = require("../styles/AppColors");
|
|
@@ -189,6 +190,7 @@ const JsonViewer = react_1.default.memo(({ data, search, forceOpen, defaultExpan
|
|
|
189
190
|
icon: (isActive) => (<NetworkIcons_1.TableIcon color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.slate400} size={12}/>),
|
|
190
191
|
},
|
|
191
192
|
]} activeKey={mode} onChange={key => setMode(key)}/>
|
|
193
|
+
<CopyButton_1.default value={data} label="JSON"/>
|
|
192
194
|
</react_native_1.View>)}
|
|
193
195
|
|
|
194
196
|
{/* ── Main View Content Area (Royal Monospace Theme) ── */}
|
|
@@ -49,6 +49,7 @@ const helpers_1 = require("../helpers");
|
|
|
49
49
|
const NetworkIcons_1 = require("./NetworkIcons");
|
|
50
50
|
// Components
|
|
51
51
|
const TouchableScale_1 = __importDefault(require("./TouchableScale"));
|
|
52
|
+
const CopyButton_1 = __importDefault(require("./CopyButton"));
|
|
52
53
|
// Stylesheet
|
|
53
54
|
const AppColors_1 = require("../styles/AppColors");
|
|
54
55
|
const AppFonts_1 = require("../styles/AppFonts");
|
|
@@ -98,9 +99,20 @@ const MetaAccordion = ({ status, statusColor, duration, size, triggeredAt, metho
|
|
|
98
99
|
<react_native_1.Pressable onPress={toggleOpen} hitSlop={12}>
|
|
99
100
|
<react_native_1.View style={styles_1.default.metaHeader}>
|
|
100
101
|
<react_native_1.Text style={styles_1.default.metaTitle}>Metadata</react_native_1.Text>
|
|
101
|
-
<react_native_1.
|
|
102
|
-
<
|
|
103
|
-
|
|
102
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
|
|
103
|
+
<CopyButton_1.default value={{
|
|
104
|
+
status: status ?? 0,
|
|
105
|
+
duration: duration != null ? `${duration} ms` : '—',
|
|
106
|
+
size: size || '—',
|
|
107
|
+
triggeredAt: triggeredAt || '',
|
|
108
|
+
method: method || 'GET',
|
|
109
|
+
contentType: contentType || 'application/json',
|
|
110
|
+
url: url || '',
|
|
111
|
+
}} label="Metadata"/>
|
|
112
|
+
<react_native_1.Animated.View style={chevronStyle}>
|
|
113
|
+
<NetworkIcons_1.ChevronIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
|
|
114
|
+
</react_native_1.Animated.View>
|
|
115
|
+
</react_native_1.View>
|
|
104
116
|
</react_native_1.View>
|
|
105
117
|
</react_native_1.Pressable>
|
|
106
118
|
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const react_1 = __importStar(require("react"));
|
|
37
|
+
const react_native_1 = require("react-native");
|
|
38
|
+
const AppColors_1 = require("../styles/AppColors");
|
|
39
|
+
const SkeletonPlaceholder = react_1.default.memo(function SkeletonPlaceholder({ cardCount = 4, }) {
|
|
40
|
+
const shimmerAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(0.35)).current;
|
|
41
|
+
(0, react_1.useEffect)(() => {
|
|
42
|
+
const animation = react_native_1.Animated.loop(react_native_1.Animated.sequence([
|
|
43
|
+
react_native_1.Animated.timing(shimmerAnim, {
|
|
44
|
+
toValue: 0.85,
|
|
45
|
+
duration: 750,
|
|
46
|
+
useNativeDriver: true,
|
|
47
|
+
}),
|
|
48
|
+
react_native_1.Animated.timing(shimmerAnim, {
|
|
49
|
+
toValue: 0.35,
|
|
50
|
+
duration: 750,
|
|
51
|
+
useNativeDriver: true,
|
|
52
|
+
}),
|
|
53
|
+
]));
|
|
54
|
+
animation.start();
|
|
55
|
+
return () => animation.stop();
|
|
56
|
+
}, [shimmerAnim]);
|
|
57
|
+
return (<react_native_1.View style={skeletonStyles.container}>
|
|
58
|
+
{/* ─── Search & Scope Toolbar Skeleton ─── */}
|
|
59
|
+
<react_native_1.View style={skeletonStyles.toolbarSkeleton}>
|
|
60
|
+
<react_native_1.Animated.View style={[
|
|
61
|
+
skeletonStyles.searchBarSkeleton,
|
|
62
|
+
{ opacity: shimmerAnim },
|
|
63
|
+
]}/>
|
|
64
|
+
<react_native_1.View style={skeletonStyles.actionButtonsRow}>
|
|
65
|
+
<react_native_1.Animated.View style={[skeletonStyles.iconButtonSkeleton, { opacity: shimmerAnim }]}/>
|
|
66
|
+
<react_native_1.Animated.View style={[skeletonStyles.iconButtonSkeleton, { opacity: shimmerAnim }]}/>
|
|
67
|
+
</react_native_1.View>
|
|
68
|
+
</react_native_1.View>
|
|
69
|
+
|
|
70
|
+
{/* ─── Quick Filter Chips Skeleton Strip ─── */}
|
|
71
|
+
<react_native_1.View style={skeletonStyles.chipStripSkeleton}>
|
|
72
|
+
<react_native_1.Animated.View style={[skeletonStyles.chipSkeleton, { width: 48, opacity: shimmerAnim }]}/>
|
|
73
|
+
<react_native_1.Animated.View style={[skeletonStyles.chipSkeleton, { width: 68, opacity: shimmerAnim }]}/>
|
|
74
|
+
<react_native_1.Animated.View style={[skeletonStyles.chipSkeleton, { width: 76, opacity: shimmerAnim }]}/>
|
|
75
|
+
<react_native_1.Animated.View style={[skeletonStyles.chipSkeleton, { width: 58, opacity: shimmerAnim }]}/>
|
|
76
|
+
</react_native_1.View>
|
|
77
|
+
|
|
78
|
+
{/* ─── List Cards Skeleton ─── */}
|
|
79
|
+
{Array.from({ length: cardCount }).map((_, i) => (<react_native_1.Animated.View key={`skeleton_card_${i}`} style={[skeletonStyles.cardSkeleton, { opacity: shimmerAnim }]}>
|
|
80
|
+
{/* Top row: Status pill + Method + Time */}
|
|
81
|
+
<react_native_1.View style={skeletonStyles.cardTopRow}>
|
|
82
|
+
<react_native_1.View style={skeletonStyles.badgeGroup}>
|
|
83
|
+
<react_native_1.View style={skeletonStyles.statusBadgeSkeleton}/>
|
|
84
|
+
<react_native_1.View style={skeletonStyles.methodBadgeSkeleton}/>
|
|
85
|
+
</react_native_1.View>
|
|
86
|
+
<react_native_1.View style={skeletonStyles.timeSkeleton}/>
|
|
87
|
+
</react_native_1.View>
|
|
88
|
+
|
|
89
|
+
{/* Middle row: URL lines */}
|
|
90
|
+
<react_native_1.View style={skeletonStyles.urlLineLong}/>
|
|
91
|
+
<react_native_1.View style={skeletonStyles.urlLineShort}/>
|
|
92
|
+
|
|
93
|
+
{/* Bottom row: Latency & Size */}
|
|
94
|
+
<react_native_1.View style={skeletonStyles.cardBottomRow}>
|
|
95
|
+
<react_native_1.View style={skeletonStyles.metaPillSkeleton}/>
|
|
96
|
+
<react_native_1.View style={skeletonStyles.metaPillSkeleton}/>
|
|
97
|
+
</react_native_1.View>
|
|
98
|
+
</react_native_1.Animated.View>))}
|
|
99
|
+
</react_native_1.View>);
|
|
100
|
+
});
|
|
101
|
+
const skeletonStyles = react_native_1.StyleSheet.create({
|
|
102
|
+
container: {
|
|
103
|
+
flex: 1,
|
|
104
|
+
paddingHorizontal: 12,
|
|
105
|
+
paddingTop: 8,
|
|
106
|
+
},
|
|
107
|
+
toolbarSkeleton: {
|
|
108
|
+
flexDirection: 'row',
|
|
109
|
+
alignItems: 'center',
|
|
110
|
+
gap: 8,
|
|
111
|
+
marginBottom: 8,
|
|
112
|
+
},
|
|
113
|
+
searchBarSkeleton: {
|
|
114
|
+
flex: 1,
|
|
115
|
+
height: 36,
|
|
116
|
+
borderRadius: 8,
|
|
117
|
+
backgroundColor: AppColors_1.AppColors.graySurface,
|
|
118
|
+
borderWidth: 1,
|
|
119
|
+
borderColor: AppColors_1.AppColors.dividerColor,
|
|
120
|
+
},
|
|
121
|
+
actionButtonsRow: {
|
|
122
|
+
flexDirection: 'row',
|
|
123
|
+
gap: 6,
|
|
124
|
+
},
|
|
125
|
+
iconButtonSkeleton: {
|
|
126
|
+
width: 36,
|
|
127
|
+
height: 36,
|
|
128
|
+
borderRadius: 8,
|
|
129
|
+
backgroundColor: AppColors_1.AppColors.graySurface,
|
|
130
|
+
borderWidth: 1,
|
|
131
|
+
borderColor: AppColors_1.AppColors.dividerColor,
|
|
132
|
+
},
|
|
133
|
+
chipStripSkeleton: {
|
|
134
|
+
flexDirection: 'row',
|
|
135
|
+
gap: 6,
|
|
136
|
+
marginBottom: 10,
|
|
137
|
+
},
|
|
138
|
+
chipSkeleton: {
|
|
139
|
+
height: 24,
|
|
140
|
+
borderRadius: 6,
|
|
141
|
+
backgroundColor: AppColors_1.AppColors.graySurface,
|
|
142
|
+
borderWidth: 1,
|
|
143
|
+
borderColor: AppColors_1.AppColors.dividerColor,
|
|
144
|
+
},
|
|
145
|
+
cardSkeleton: {
|
|
146
|
+
backgroundColor: AppColors_1.AppColors.primaryLight,
|
|
147
|
+
borderRadius: 10,
|
|
148
|
+
padding: 12,
|
|
149
|
+
marginBottom: 8,
|
|
150
|
+
borderWidth: 1,
|
|
151
|
+
borderColor: AppColors_1.AppColors.dividerColor,
|
|
152
|
+
},
|
|
153
|
+
cardTopRow: {
|
|
154
|
+
flexDirection: 'row',
|
|
155
|
+
justifyContent: 'space-between',
|
|
156
|
+
alignItems: 'center',
|
|
157
|
+
marginBottom: 8,
|
|
158
|
+
},
|
|
159
|
+
badgeGroup: {
|
|
160
|
+
flexDirection: 'row',
|
|
161
|
+
alignItems: 'center',
|
|
162
|
+
gap: 6,
|
|
163
|
+
},
|
|
164
|
+
statusBadgeSkeleton: {
|
|
165
|
+
width: 38,
|
|
166
|
+
height: 18,
|
|
167
|
+
borderRadius: 4,
|
|
168
|
+
backgroundColor: AppColors_1.AppColors.graySurface,
|
|
169
|
+
},
|
|
170
|
+
methodBadgeSkeleton: {
|
|
171
|
+
width: 44,
|
|
172
|
+
height: 18,
|
|
173
|
+
borderRadius: 4,
|
|
174
|
+
backgroundColor: AppColors_1.AppColors.graySurface,
|
|
175
|
+
},
|
|
176
|
+
timeSkeleton: {
|
|
177
|
+
width: 48,
|
|
178
|
+
height: 12,
|
|
179
|
+
borderRadius: 4,
|
|
180
|
+
backgroundColor: AppColors_1.AppColors.graySurface,
|
|
181
|
+
},
|
|
182
|
+
urlLineLong: {
|
|
183
|
+
height: 13,
|
|
184
|
+
borderRadius: 4,
|
|
185
|
+
backgroundColor: AppColors_1.AppColors.graySurface,
|
|
186
|
+
marginBottom: 5,
|
|
187
|
+
width: '90%',
|
|
188
|
+
},
|
|
189
|
+
urlLineShort: {
|
|
190
|
+
height: 11,
|
|
191
|
+
borderRadius: 4,
|
|
192
|
+
backgroundColor: AppColors_1.AppColors.graySurface,
|
|
193
|
+
marginBottom: 8,
|
|
194
|
+
width: '55%',
|
|
195
|
+
},
|
|
196
|
+
cardBottomRow: {
|
|
197
|
+
flexDirection: 'row',
|
|
198
|
+
gap: 8,
|
|
199
|
+
marginTop: 2,
|
|
200
|
+
},
|
|
201
|
+
metaPillSkeleton: {
|
|
202
|
+
width: 52,
|
|
203
|
+
height: 14,
|
|
204
|
+
borderRadius: 4,
|
|
205
|
+
backgroundColor: AppColors_1.AppColors.graySurface,
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
exports.default = SkeletonPlaceholder;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const LIB_VERSION = "2.
|
|
1
|
+
export declare const LIB_VERSION = "2.3.1";
|
|
@@ -3,4 +3,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.LIB_VERSION = void 0;
|
|
4
4
|
// AUTO-GENERATED FILE — do not edit by hand.
|
|
5
5
|
// Regenerated from package.json on every build by scripts/gen-version.js.
|
|
6
|
-
exports.LIB_VERSION = '2.
|
|
6
|
+
exports.LIB_VERSION = '2.3.1';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RouteInfo } from "../types";
|
|
1
2
|
type NetworkLog = {
|
|
2
3
|
id: number;
|
|
3
4
|
url: string;
|
|
@@ -11,7 +12,9 @@ type NetworkLog = {
|
|
|
11
12
|
client?: string;
|
|
12
13
|
requestHeaders?: Record<string, string>;
|
|
13
14
|
responseHeaders?: Record<string, string>;
|
|
15
|
+
routeInfo?: RouteInfo;
|
|
14
16
|
};
|
|
17
|
+
export declare const setRouteInfoProvider: (provider: (() => RouteInfo | null) | null) => void;
|
|
15
18
|
export declare const setNetworkModuleEnabled: (enabled: boolean) => void;
|
|
16
19
|
export declare const getNetworkModuleEnabled: () => boolean;
|
|
17
20
|
export declare const subscribeNetworkLogs: (callback: (logs: NetworkLog[]) => void) => () => void;
|
|
@@ -3,13 +3,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.addAxiosInterceptors = exports.setupNetworkLogger = exports.pruneNetworkLogs = exports.getMaxNetworkLogsLimit = exports.setMaxNetworkLogsLimit = exports.getNetworkLogs = exports.clearNetworkLogs = exports.subscribeNetworkLogs = exports.getNetworkModuleEnabled = exports.setNetworkModuleEnabled = void 0;
|
|
6
|
+
exports.addAxiosInterceptors = exports.setupNetworkLogger = exports.pruneNetworkLogs = exports.getMaxNetworkLogsLimit = exports.setMaxNetworkLogsLimit = exports.getNetworkLogs = exports.clearNetworkLogs = exports.subscribeNetworkLogs = exports.getNetworkModuleEnabled = exports.setNetworkModuleEnabled = exports.setRouteInfoProvider = void 0;
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
8
|
const crashHandler_1 = require("./crashHandler");
|
|
9
9
|
let logs = [];
|
|
10
10
|
let listeners = [];
|
|
11
11
|
let counter = 0;
|
|
12
12
|
let isNetworkModuleEnabled = true;
|
|
13
|
+
let currentRouteProvider = null;
|
|
14
|
+
const setRouteInfoProvider = (provider) => {
|
|
15
|
+
currentRouteProvider = provider;
|
|
16
|
+
};
|
|
17
|
+
exports.setRouteInfoProvider = setRouteInfoProvider;
|
|
13
18
|
const setNetworkModuleEnabled = (enabled) => {
|
|
14
19
|
isNetworkModuleEnabled = enabled;
|
|
15
20
|
};
|
|
@@ -199,6 +204,7 @@ const setupNetworkLogger = () => {
|
|
|
199
204
|
else if (caller?.toLowerCase().includes('axios')) {
|
|
200
205
|
client = 'axios';
|
|
201
206
|
}
|
|
207
|
+
const currentRoute = currentRouteProvider ? currentRouteProvider() : null;
|
|
202
208
|
addOrUpdateLog({
|
|
203
209
|
id,
|
|
204
210
|
url: finalUrl,
|
|
@@ -206,6 +212,7 @@ const setupNetworkLogger = () => {
|
|
|
206
212
|
startTime: start,
|
|
207
213
|
caller,
|
|
208
214
|
client,
|
|
215
|
+
routeInfo: currentRoute || undefined,
|
|
209
216
|
request: method === "GET" ? undefined : parseRequestData(options?.body),
|
|
210
217
|
requestHeaders,
|
|
211
218
|
});
|
|
@@ -313,6 +320,7 @@ const addAxiosInterceptors = (axiosInstance) => {
|
|
|
313
320
|
config.__logId = id;
|
|
314
321
|
config.__logStart = start;
|
|
315
322
|
config.__logCaller = caller;
|
|
323
|
+
const currentRoute = currentRouteProvider ? currentRouteProvider() : null;
|
|
316
324
|
addOrUpdateLog({
|
|
317
325
|
id,
|
|
318
326
|
url,
|
|
@@ -320,6 +328,7 @@ const addAxiosInterceptors = (axiosInstance) => {
|
|
|
320
328
|
startTime: start,
|
|
321
329
|
caller,
|
|
322
330
|
client: 'axios',
|
|
331
|
+
routeInfo: currentRoute || undefined,
|
|
323
332
|
request: method === "GET" ? undefined : parseRequestData(config.data),
|
|
324
333
|
requestHeaders: normaliseHeaders(config.headers),
|
|
325
334
|
});
|
|
@@ -37,11 +37,11 @@ export declare const getRegisteredMMKVInstanceIds: () => string[];
|
|
|
37
37
|
*/
|
|
38
38
|
export declare const calculateByteSize: (str: string) => number;
|
|
39
39
|
/**
|
|
40
|
-
* Determine type and format value safely
|
|
40
|
+
* Determine type and format value safely without blocking JS thread
|
|
41
41
|
*/
|
|
42
42
|
export declare const analyzeStorageValue: (rawVal: any) => {
|
|
43
43
|
strVal: string;
|
|
44
|
-
|
|
44
|
+
parsedValue?: any;
|
|
45
45
|
type: "json" | "string" | "number" | "boolean" | "null";
|
|
46
46
|
byteSize: number;
|
|
47
47
|
};
|