react-native-inapp-inspector 2.2.9 → 2.3.0
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/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 +19 -3
- package/dist/commonjs/components/JsonViewer.js +2 -0
- package/dist/commonjs/components/MetaAccordion.js +15 -3
- 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/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 +80 -11
- 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 +1 -0
- 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/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 +19 -3
- package/dist/esm/components/JsonViewer.js +2 -0
- package/dist/esm/components/MetaAccordion.js +15 -3
- 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/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 +68 -12
- 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 +1 -0
- 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/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 +21 -3
- package/src/components/JsonViewer.tsx +2 -0
- package/src/components/MetaAccordion.tsx +18 -3
- package/src/constants/version.ts +1 -1
- package/src/customHooks/networkLogger.ts +15 -0
- 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 +89 -11
- package/src/styles/AppColors.ts +9 -0
- package/src/styles/AppFonts.ts +16 -0
- package/src/types/interfaces.ts +1 -0
package/dist/esm/index.js
CHANGED
|
@@ -8,12 +8,12 @@ import ErrorBoundary from './components/ErrorBoundary';
|
|
|
8
8
|
import MainScreen from './components/Inspector/MainScreen';
|
|
9
9
|
import { InspectorContext, animateNextLayout, } from './components/Inspector/InspectorContext';
|
|
10
10
|
// Helpers
|
|
11
|
-
import { formatDisplayUrl, getNavigationInfo, deduplicateLogs, getDomainColor, getEventCategory, matchNetworkLogQuery, setupMemoryWarningHandler, } from './helpers';
|
|
11
|
+
import { formatDisplayUrl, getNavigationInfo, getLogPageName, deduplicateLogs, getDomainColor, getEventCategory, matchNetworkLogQuery, setupMemoryWarningHandler, } from './helpers';
|
|
12
12
|
// #5 — settings persistence
|
|
13
13
|
import { loadSettings, saveSettings, setCustomStorage, clearPersistedSettings, calculateRamBasedLimits, } from './helpers/settingsStore';
|
|
14
14
|
import { getNativeSystemMetrics, pushNativeLogRecord, fetchNativeCachedPage, } from './native/NativeInspector';
|
|
15
15
|
// Network
|
|
16
|
-
import { setupNetworkLogger, clearNetworkLogs, subscribeNetworkLogs, setNetworkModuleEnabled, setMaxNetworkLogsLimit, } from './customHooks/networkLogger';
|
|
16
|
+
import { setupNetworkLogger, clearNetworkLogs, subscribeNetworkLogs, setNetworkModuleEnabled, setMaxNetworkLogsLimit, setRouteInfoProvider, } from './customHooks/networkLogger';
|
|
17
17
|
// Console
|
|
18
18
|
import { setupConsoleLogger, clearConsoleLogs, subscribeConsoleLogs, setConsoleModuleEnabled, } from './customHooks/consoleLogger';
|
|
19
19
|
import { IGNORED_LOG_PREFIXES } from './customHooks/logFilters';
|
|
@@ -183,8 +183,8 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
183
183
|
bundle: false,
|
|
184
184
|
performance: false,
|
|
185
185
|
crash: false,
|
|
186
|
-
device:
|
|
187
|
-
storage:
|
|
186
|
+
device: false,
|
|
187
|
+
storage: false,
|
|
188
188
|
});
|
|
189
189
|
const [maxNetworkLogs, setMaxNetworkLogs] = useState(100);
|
|
190
190
|
const [maxAnalyticsEventsLimit, setMaxAnalyticsEventsLimit] = useState(75);
|
|
@@ -239,8 +239,8 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
239
239
|
bundle: false,
|
|
240
240
|
performance: false,
|
|
241
241
|
crash: false,
|
|
242
|
-
device:
|
|
243
|
-
storage:
|
|
242
|
+
device: false,
|
|
243
|
+
storage: false,
|
|
244
244
|
});
|
|
245
245
|
setDefaultTab('apis');
|
|
246
246
|
setIsAutoRamLimitEnabled(true);
|
|
@@ -314,6 +314,8 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
314
314
|
bundle: false,
|
|
315
315
|
performance: false,
|
|
316
316
|
crash: false,
|
|
317
|
+
device: false,
|
|
318
|
+
storage: false,
|
|
317
319
|
},
|
|
318
320
|
...(saved.tabVisibility || {}),
|
|
319
321
|
apis: true,
|
|
@@ -539,12 +541,21 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
539
541
|
const navigationContext = React.useContext(NavigationContext);
|
|
540
542
|
const hasNavigationContext = navigationContext !== undefined;
|
|
541
543
|
const currentRouteRef = useRef({
|
|
542
|
-
path: '
|
|
544
|
+
path: '',
|
|
543
545
|
params: null,
|
|
544
546
|
});
|
|
547
|
+
useEffect(() => {
|
|
548
|
+
setRouteInfoProvider(() => currentRouteRef.current);
|
|
549
|
+
return () => {
|
|
550
|
+
setRouteInfoProvider(null);
|
|
551
|
+
};
|
|
552
|
+
}, []);
|
|
545
553
|
useEffect(() => {
|
|
546
554
|
if (navState) {
|
|
547
|
-
|
|
555
|
+
const info = getNavigationInfo(navState);
|
|
556
|
+
if (info?.path) {
|
|
557
|
+
currentRouteRef.current = info;
|
|
558
|
+
}
|
|
548
559
|
}
|
|
549
560
|
}, [navState]);
|
|
550
561
|
useEffect(() => {
|
|
@@ -553,9 +564,22 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
553
564
|
const updateState = () => {
|
|
554
565
|
try {
|
|
555
566
|
if (typeof navigationRef.isReady === 'function' && navigationRef.isReady()) {
|
|
567
|
+
const currentRoute = typeof navigationRef.getCurrentRoute === 'function'
|
|
568
|
+
? navigationRef.getCurrentRoute()
|
|
569
|
+
: null;
|
|
570
|
+
if (currentRoute?.name) {
|
|
571
|
+
currentRouteRef.current = {
|
|
572
|
+
path: currentRoute.name,
|
|
573
|
+
params: currentRoute.params || null,
|
|
574
|
+
};
|
|
575
|
+
}
|
|
556
576
|
const state = navigationRef.getRootState();
|
|
557
577
|
if (state) {
|
|
558
578
|
setNavState(state);
|
|
579
|
+
const routeInfo = getNavigationInfo(state);
|
|
580
|
+
if (routeInfo?.path) {
|
|
581
|
+
currentRouteRef.current = routeInfo;
|
|
582
|
+
}
|
|
559
583
|
}
|
|
560
584
|
}
|
|
561
585
|
}
|
|
@@ -867,7 +891,9 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
867
891
|
if (freshIds.size > 0) {
|
|
868
892
|
freshIds.forEach(id => {
|
|
869
893
|
if (!logRouteMapRef.current.has(id)) {
|
|
870
|
-
|
|
894
|
+
const matchedLog = deduped.find(l => l.id === id);
|
|
895
|
+
const resolvedRoute = matchedLog?.routeInfo || currentRouteRef.current;
|
|
896
|
+
logRouteMapRef.current.set(id, resolvedRoute);
|
|
871
897
|
}
|
|
872
898
|
});
|
|
873
899
|
setNewLogIds(freshIds);
|
|
@@ -880,6 +906,12 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
880
906
|
const deduped = deduplicateLogs(raw);
|
|
881
907
|
const incoming = new Set(deduped.map(l => l.id));
|
|
882
908
|
prevLogIdsRef.current = incoming;
|
|
909
|
+
deduped.forEach(l => {
|
|
910
|
+
if (!logRouteMapRef.current.has(l.id)) {
|
|
911
|
+
const resolvedRoute = l?.routeInfo || currentRouteRef.current;
|
|
912
|
+
logRouteMapRef.current.set(l.id, resolvedRoute);
|
|
913
|
+
}
|
|
914
|
+
});
|
|
883
915
|
setLogs(deduped);
|
|
884
916
|
}
|
|
885
917
|
else {
|
|
@@ -1151,8 +1183,8 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
1151
1183
|
const groups = [];
|
|
1152
1184
|
for (let i = 0; i < filteredLogs.length; i++) {
|
|
1153
1185
|
const log = filteredLogs[i];
|
|
1154
|
-
const routeInfo = logRouteMapRef.current.get(log.id);
|
|
1155
|
-
const pageName = routeInfo
|
|
1186
|
+
const routeInfo = logRouteMapRef.current.get(log.id) || log?.routeInfo;
|
|
1187
|
+
const pageName = getLogPageName(log, routeInfo);
|
|
1156
1188
|
if (groups.length === 0 ||
|
|
1157
1189
|
groups[groups.length - 1].pageName !== pageName) {
|
|
1158
1190
|
groups.push({ pageName, color: getDomainColor(pageName), logs: [] });
|
|
@@ -1405,7 +1437,28 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
1405
1437
|
log.type || '',
|
|
1406
1438
|
log.sourceMethod || '',
|
|
1407
1439
|
].join(' ').toLowerCase();
|
|
1408
|
-
return queryTokens.every(token =>
|
|
1440
|
+
return queryTokens.every(token => {
|
|
1441
|
+
if (token.startsWith('level:') || token.startsWith('is:') || token.startsWith('type:')) {
|
|
1442
|
+
const flag = token.replace(/^(level:|is:|type:)/, '').trim();
|
|
1443
|
+
if (flag === 'error' || flag === 'err')
|
|
1444
|
+
return log.type === 'error';
|
|
1445
|
+
if (flag === 'warn' || flag === 'warning')
|
|
1446
|
+
return log.type === 'warn';
|
|
1447
|
+
if (flag === 'info')
|
|
1448
|
+
return log.type === 'info';
|
|
1449
|
+
if (flag === 'log')
|
|
1450
|
+
return log.sourceMethod === 'log';
|
|
1451
|
+
if (flag === 'analytics')
|
|
1452
|
+
return (log.message || '').toLowerCase().includes('[analytics');
|
|
1453
|
+
}
|
|
1454
|
+
if (token === 'error' || token === 'err') {
|
|
1455
|
+
return log.type === 'error' || searchTarget.includes(token);
|
|
1456
|
+
}
|
|
1457
|
+
if (token === 'warn' || token === 'warning') {
|
|
1458
|
+
return log.type === 'warn' || searchTarget.includes(token);
|
|
1459
|
+
}
|
|
1460
|
+
return searchTarget.includes(token);
|
|
1461
|
+
});
|
|
1409
1462
|
});
|
|
1410
1463
|
}
|
|
1411
1464
|
// #7 — apply sort order (newest/oldest first)
|
|
@@ -1824,3 +1877,6 @@ export { setMaxPerformanceEventsLimit, getMaxPerformanceEventsLimit, prunePerfor
|
|
|
1824
1877
|
export { BrandSquareIcon, BrandCircleIcon, } from './components/NetworkIcons';
|
|
1825
1878
|
export { connectAsyncStorage, connectMMKV, isAsyncStorageConnected, isMMKVConnected, getRegisteredMMKVInstanceIds, fetchStorageEntries, setStorageEntry, removeStorageEntry, clearStorageDriver, subscribeToStorageChanges, } from './customHooks/storageInspector';
|
|
1826
1879
|
export { ActiveTab, Method, StatusFilter, SortOrder, LocalFilter, ModalAnimationType, SettingsPage, SettingsSubTab, LogFilter, ConsoleLogType, AnalyticsEventSource, GAEventCategory, StackFrameType, DiffResultType, BundleSubTab, PerformanceSubTab, CrashType, CrashExportFormat, CrashDetailSubTab, CrashFilterType, BreadcrumbType, } from './types';
|
|
1880
|
+
export { AppFonts, setAppFonts, } from './styles/AppFonts';
|
|
1881
|
+
export { AppColors, setAppColors, getThemeColors, updateAppColorsTheme, } from './styles/AppColors';
|
|
1882
|
+
export { t, i18n, useTranslation, setLanguage, addTranslations, setTranslations, I18nextProvider, } from './i18n';
|
|
@@ -344,4 +344,8 @@ export declare const getThemeColors: (isDark: boolean) => {
|
|
|
344
344
|
};
|
|
345
345
|
export declare const AppColors: typeof LightColors;
|
|
346
346
|
export declare const updateAppColorsTheme: (isDark: boolean) => void;
|
|
347
|
+
/**
|
|
348
|
+
* Configure or override specific color tokens used throughout the inspector.
|
|
349
|
+
*/
|
|
350
|
+
export declare const setAppColors: (customColors: Partial<typeof LightColors>) => void;
|
|
347
351
|
export default AppColors;
|
|
@@ -384,4 +384,13 @@ Object.assign(AppColors, LightColors);
|
|
|
384
384
|
export const updateAppColorsTheme = (isDark) => {
|
|
385
385
|
Object.assign(AppColors, getThemeColors(isDark));
|
|
386
386
|
};
|
|
387
|
+
/**
|
|
388
|
+
* Configure or override specific color tokens used throughout the inspector.
|
|
389
|
+
*/
|
|
390
|
+
export const setAppColors = (customColors) => {
|
|
391
|
+
if (!customColors || typeof customColors !== 'object')
|
|
392
|
+
return;
|
|
393
|
+
Object.assign(AppColors, customColors);
|
|
394
|
+
Object.assign(LightColors, customColors);
|
|
395
|
+
};
|
|
387
396
|
export default AppColors;
|
|
@@ -1,7 +1,18 @@
|
|
|
1
|
+
export interface AppFontConfig {
|
|
2
|
+
interRegular?: string;
|
|
3
|
+
interMedium?: string;
|
|
4
|
+
interBold?: string;
|
|
5
|
+
Sfprotext?: string;
|
|
6
|
+
}
|
|
1
7
|
export declare const AppFonts: {
|
|
2
8
|
interRegular: string;
|
|
3
9
|
interMedium: string;
|
|
4
10
|
interBold: string;
|
|
5
11
|
Sfprotext: string;
|
|
6
12
|
};
|
|
13
|
+
/**
|
|
14
|
+
* Configure or override font families used across all inspector screens.
|
|
15
|
+
* Useful when integrating into apps with custom font setups or system fonts.
|
|
16
|
+
*/
|
|
17
|
+
export declare const setAppFonts: (customFonts: Partial<typeof AppFonts>) => void;
|
|
7
18
|
export default AppFonts;
|
|
@@ -4,4 +4,13 @@ export const AppFonts = {
|
|
|
4
4
|
interBold: 'Inter-Bold',
|
|
5
5
|
Sfprotext: 'Inter-Regular',
|
|
6
6
|
};
|
|
7
|
+
/**
|
|
8
|
+
* Configure or override font families used across all inspector screens.
|
|
9
|
+
* Useful when integrating into apps with custom font setups or system fonts.
|
|
10
|
+
*/
|
|
11
|
+
export const setAppFonts = (customFonts) => {
|
|
12
|
+
if (!customFonts || typeof customFonts !== 'object')
|
|
13
|
+
return;
|
|
14
|
+
Object.assign(AppFonts, customFonts);
|
|
15
|
+
};
|
|
7
16
|
export default AppFonts;
|
|
@@ -106,6 +106,7 @@ export interface NetworkLog {
|
|
|
106
106
|
/** Client identifier: axios, fetch, xhr, apollo, etc. */
|
|
107
107
|
client?: 'axios' | 'fetch' | 'xhr' | 'apollo' | 'graphql' | string;
|
|
108
108
|
caller?: string;
|
|
109
|
+
routeInfo?: RouteInfo;
|
|
109
110
|
}
|
|
110
111
|
export interface RouteInfo {
|
|
111
112
|
path: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-inapp-inspector",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "The zero-config, all-in-one in-app debugger for React Native & Expo. Inspect Network (fetch/axios), Console logs, Stack Traces, Redux State, Firebase Analytics, and JS Bundle size directly on device.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -34,8 +34,12 @@ export const AppHeaderLogo: React.FC<AppHeaderLogoProps> = ({
|
|
|
34
34
|
return (
|
|
35
35
|
<View
|
|
36
36
|
style={[
|
|
37
|
-
logoStyles.
|
|
38
|
-
{
|
|
37
|
+
logoStyles.svgContainer,
|
|
38
|
+
{
|
|
39
|
+
width: size,
|
|
40
|
+
height: size,
|
|
41
|
+
borderRadius: Math.round(size * 0.23),
|
|
42
|
+
},
|
|
39
43
|
]}>
|
|
40
44
|
{clonedIcon}
|
|
41
45
|
</View>
|
|
@@ -44,8 +48,12 @@ export const AppHeaderLogo: React.FC<AppHeaderLogoProps> = ({
|
|
|
44
48
|
return (
|
|
45
49
|
<View
|
|
46
50
|
style={[
|
|
47
|
-
logoStyles.
|
|
48
|
-
{
|
|
51
|
+
logoStyles.imageContainer,
|
|
52
|
+
{
|
|
53
|
+
width: size,
|
|
54
|
+
height: size,
|
|
55
|
+
borderRadius: Math.round(size * 0.23),
|
|
56
|
+
},
|
|
49
57
|
]}>
|
|
50
58
|
<Image
|
|
51
59
|
source={customIcon as ImageSourcePropType}
|
|
@@ -65,7 +73,15 @@ export const AppHeaderLogo: React.FC<AppHeaderLogoProps> = ({
|
|
|
65
73
|
});
|
|
66
74
|
|
|
67
75
|
return (
|
|
68
|
-
<View
|
|
76
|
+
<View
|
|
77
|
+
style={[
|
|
78
|
+
logoStyles.imageContainer,
|
|
79
|
+
{
|
|
80
|
+
width: size,
|
|
81
|
+
height: size,
|
|
82
|
+
borderRadius: Math.round(size * 0.23),
|
|
83
|
+
},
|
|
84
|
+
]}>
|
|
69
85
|
<Image
|
|
70
86
|
source={nativeSource}
|
|
71
87
|
style={logoStyles.image}
|
|
@@ -80,8 +96,12 @@ export const AppHeaderLogo: React.FC<AppHeaderLogoProps> = ({
|
|
|
80
96
|
return (
|
|
81
97
|
<View
|
|
82
98
|
style={[
|
|
83
|
-
logoStyles.
|
|
84
|
-
{
|
|
99
|
+
logoStyles.svgContainer,
|
|
100
|
+
{
|
|
101
|
+
width: size,
|
|
102
|
+
height: size,
|
|
103
|
+
borderRadius: Math.round(size * 0.23),
|
|
104
|
+
},
|
|
85
105
|
]}>
|
|
86
106
|
<BrandSquareIcon size={size} />
|
|
87
107
|
</View>
|
|
@@ -89,20 +109,34 @@ export const AppHeaderLogo: React.FC<AppHeaderLogoProps> = ({
|
|
|
89
109
|
};
|
|
90
110
|
|
|
91
111
|
const logoStyles = StyleSheet.create({
|
|
92
|
-
|
|
93
|
-
|
|
112
|
+
svgContainer: {
|
|
113
|
+
overflow: 'hidden',
|
|
114
|
+
alignItems: 'center',
|
|
115
|
+
justifyContent: 'center',
|
|
116
|
+
shadowColor: '#000',
|
|
117
|
+
shadowOffset: {width: 0, height: 2},
|
|
118
|
+
shadowOpacity: 0.25,
|
|
119
|
+
shadowRadius: 3,
|
|
120
|
+
elevation: 3,
|
|
121
|
+
},
|
|
122
|
+
imageContainer: {
|
|
94
123
|
overflow: 'hidden',
|
|
95
124
|
backgroundColor: 'rgba(255, 255, 255, 0.15)',
|
|
96
125
|
borderWidth: 1,
|
|
97
|
-
borderColor: 'rgba(255, 255, 255, 0.
|
|
98
|
-
padding: 2
|
|
126
|
+
borderColor: 'rgba(255, 255, 255, 0.35)',
|
|
127
|
+
padding: 2,
|
|
99
128
|
alignItems: 'center',
|
|
100
129
|
justifyContent: 'center',
|
|
130
|
+
shadowColor: '#000',
|
|
131
|
+
shadowOffset: {width: 0, height: 2},
|
|
132
|
+
shadowOpacity: 0.25,
|
|
133
|
+
shadowRadius: 3,
|
|
134
|
+
elevation: 3,
|
|
101
135
|
},
|
|
102
136
|
image: {
|
|
103
137
|
width: '100%',
|
|
104
138
|
height: '100%',
|
|
105
|
-
borderRadius:
|
|
139
|
+
borderRadius: 8,
|
|
106
140
|
},
|
|
107
141
|
});
|
|
108
142
|
|
|
@@ -8,7 +8,6 @@ import Svg, {
|
|
|
8
8
|
RadialGradient,
|
|
9
9
|
Stop,
|
|
10
10
|
Rect,
|
|
11
|
-
Ellipse,
|
|
12
11
|
Line,
|
|
13
12
|
} from 'react-native-svg';
|
|
14
13
|
|
|
@@ -16,117 +15,167 @@ export const BrandSquareIcon = ({size = 56}: {size?: number}) => {
|
|
|
16
15
|
return (
|
|
17
16
|
<Svg width={size} height={size} viewBox="0 0 256 256" fill="none">
|
|
18
17
|
<Defs>
|
|
18
|
+
{/* App Tile Background - Crisp Royal Deep Violet to Midnight */}
|
|
19
19
|
<LinearGradient id="bs_tile" x1="0" y1="0" x2="256" y2="256" gradientUnits="userSpaceOnUse">
|
|
20
|
-
<Stop offset="0" stopColor="#1E1B4B" />
|
|
21
|
-
<Stop offset="
|
|
20
|
+
<Stop offset="0%" stopColor="#1E1B4B" />
|
|
21
|
+
<Stop offset="50%" stopColor="#18182F" />
|
|
22
|
+
<Stop offset="100%" stopColor="#0B0F19" />
|
|
22
23
|
</LinearGradient>
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
<Stop offset="
|
|
24
|
+
|
|
25
|
+
{/* Outer Neon Cyber Border */}
|
|
26
|
+
<LinearGradient id="bs_border" x1="0" y1="0" x2="256" y2="256" gradientUnits="userSpaceOnUse">
|
|
27
|
+
<Stop offset="0%" stopColor="#818CF8" stopOpacity={0.9} />
|
|
28
|
+
<Stop offset="45%" stopColor="#C084FC" stopOpacity={0.8} />
|
|
29
|
+
<Stop offset="80%" stopColor="#F472B6" stopOpacity={0.85} />
|
|
30
|
+
<Stop offset="100%" stopColor="#38BDF8" stopOpacity={0.9} />
|
|
27
31
|
</LinearGradient>
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
|
|
33
|
+
{/* Ambient Top Glow */}
|
|
34
|
+
<RadialGradient id="bs_top_glow" cx="50%" cy="15%" r="65%">
|
|
35
|
+
<Stop offset="0%" stopColor="#818CF8" stopOpacity={0.35} />
|
|
36
|
+
<Stop offset="60%" stopColor="#A855F7" stopOpacity={0.12} />
|
|
37
|
+
<Stop offset="100%" stopColor="#1E1B4B" stopOpacity={0} />
|
|
38
|
+
</RadialGradient>
|
|
39
|
+
|
|
40
|
+
{/* Owl Outer Body Gradient - High Contrast */}
|
|
41
|
+
<LinearGradient id="bs_body" x1="64" y1="40" x2="192" y2="220" gradientUnits="userSpaceOnUse">
|
|
42
|
+
<Stop offset="0%" stopColor="#3730A3" />
|
|
43
|
+
<Stop offset="50%" stopColor="#2E1065" />
|
|
44
|
+
<Stop offset="100%" stopColor="#17123A" />
|
|
31
45
|
</LinearGradient>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
<Stop offset="
|
|
46
|
+
|
|
47
|
+
{/* Neon Cyber Beam Stroke */}
|
|
48
|
+
<LinearGradient id="bs_beam" x1="40" y1="40" x2="220" y2="220" gradientUnits="userSpaceOnUse">
|
|
49
|
+
<Stop offset="0%" stopColor="#67E8F9" />
|
|
50
|
+
<Stop offset="35%" stopColor="#818CF8" />
|
|
51
|
+
<Stop offset="70%" stopColor="#C084FC" />
|
|
52
|
+
<Stop offset="100%" stopColor="#F472B6" />
|
|
53
|
+
</LinearGradient>
|
|
54
|
+
|
|
55
|
+
{/* Eyes Radiant Iris */}
|
|
56
|
+
<RadialGradient id="bs_iris" cx="38%" cy="36%" r="65%">
|
|
57
|
+
<Stop offset="0%" stopColor="#FEF08A" />
|
|
58
|
+
<Stop offset="40%" stopColor="#FBBF24" />
|
|
59
|
+
<Stop offset="80%" stopColor="#F59E0B" />
|
|
60
|
+
<Stop offset="100%" stopColor="#D97706" />
|
|
36
61
|
</RadialGradient>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
62
|
+
|
|
63
|
+
{/* Beak Gradient */}
|
|
64
|
+
<LinearGradient id="bs_beak" x1="124" y1="120" x2="132" y2="136" gradientUnits="userSpaceOnUse">
|
|
65
|
+
<Stop offset="0%" stopColor="#FDE047" />
|
|
66
|
+
<Stop offset="100%" stopColor="#EA580C" />
|
|
40
67
|
</LinearGradient>
|
|
68
|
+
|
|
69
|
+
{/* Diagnostic Lens Glass Flare */}
|
|
70
|
+
<RadialGradient id="bs_lens" cx="40%" cy="35%" r="65%">
|
|
71
|
+
<Stop offset="0%" stopColor="#A5F3FC" stopOpacity={0.4} />
|
|
72
|
+
<Stop offset="50%" stopColor="#38BDF8" stopOpacity={0.18} />
|
|
73
|
+
<Stop offset="100%" stopColor="#0284C7" stopOpacity={0.05} />
|
|
74
|
+
</RadialGradient>
|
|
41
75
|
</Defs>
|
|
42
76
|
|
|
43
|
-
{/* Rounded App Tile
|
|
44
|
-
<Rect x="
|
|
77
|
+
{/* ── 1. Rounded App Tile Base (Full Edge-to-Edge) ── */}
|
|
78
|
+
<Rect x="2" y="2" width="252" height="252" rx="58" fill="url(#bs_tile)" />
|
|
79
|
+
<Rect x="2" y="2" width="252" height="252" rx="58" fill="url(#bs_top_glow)" />
|
|
45
80
|
<Rect
|
|
46
|
-
x="
|
|
47
|
-
y="
|
|
48
|
-
width="
|
|
49
|
-
height="
|
|
50
|
-
rx="
|
|
81
|
+
x="2"
|
|
82
|
+
y="2"
|
|
83
|
+
width="252"
|
|
84
|
+
height="252"
|
|
85
|
+
rx="58"
|
|
51
86
|
fill="none"
|
|
52
|
-
stroke="url(#
|
|
53
|
-
strokeWidth="3"
|
|
54
|
-
strokeOpacity={0.4}
|
|
87
|
+
stroke="url(#bs_border)"
|
|
88
|
+
strokeWidth="3.5"
|
|
55
89
|
/>
|
|
56
90
|
|
|
57
|
-
{/* Owl Outer
|
|
91
|
+
{/* ── 2. Owl Outer Wings (Layered behind) ── */}
|
|
58
92
|
<Path
|
|
59
|
-
d="
|
|
60
|
-
fill="
|
|
93
|
+
d="M62 120 C42 152 46 194 76 210 C68 178 66 146 80 120 Z"
|
|
94
|
+
fill="#1E1B4B"
|
|
61
95
|
stroke="url(#bs_beam)"
|
|
62
|
-
strokeWidth="
|
|
63
|
-
|
|
96
|
+
strokeWidth="3"
|
|
97
|
+
strokeOpacity={0.75}
|
|
64
98
|
/>
|
|
65
|
-
|
|
66
|
-
{/* Wings */}
|
|
67
99
|
<Path
|
|
68
|
-
d="
|
|
100
|
+
d="M194 120 C214 152 210 194 180 210 C188 178 190 146 176 120 Z"
|
|
69
101
|
fill="#1E1B4B"
|
|
70
|
-
stroke="#
|
|
71
|
-
strokeWidth="
|
|
72
|
-
strokeOpacity={0.
|
|
102
|
+
stroke="url(#bs_beam)"
|
|
103
|
+
strokeWidth="3"
|
|
104
|
+
strokeOpacity={0.75}
|
|
73
105
|
/>
|
|
106
|
+
|
|
107
|
+
{/* ── 3. Owl Body Contour ── */}
|
|
74
108
|
<Path
|
|
75
|
-
d="
|
|
76
|
-
fill="#
|
|
77
|
-
stroke="#
|
|
78
|
-
strokeWidth="
|
|
79
|
-
|
|
109
|
+
d="M58 146 C54 98 68 64 88 52 L98 34 L118 56 Q128 50 138 56 L158 34 L168 52 C188 64 202 98 198 146 C202 180 186 208 152 216 C140 220 116 220 104 216 C70 208 54 180 58 146 Z"
|
|
110
|
+
fill="url(#bs_body)"
|
|
111
|
+
stroke="url(#bs_beam)"
|
|
112
|
+
strokeWidth="4.5"
|
|
113
|
+
strokeLinejoin="round"
|
|
80
114
|
/>
|
|
81
115
|
|
|
82
|
-
{/*
|
|
116
|
+
{/* Inner Ear Highlights */}
|
|
117
|
+
<Path d="M98 42 L112 56 L102 57 Z" fill="#67E8F9" opacity={0.6} />
|
|
118
|
+
<Path d="M158 42 L144 56 L154 57 Z" fill="#F472B6" opacity={0.6} />
|
|
119
|
+
|
|
120
|
+
{/* ── 4. Chest Terminal & Code Braces ── */}
|
|
83
121
|
<Rect
|
|
84
|
-
x="
|
|
85
|
-
y="
|
|
86
|
-
width="
|
|
87
|
-
height="
|
|
88
|
-
rx="
|
|
89
|
-
fill="#
|
|
122
|
+
x="98"
|
|
123
|
+
y="162"
|
|
124
|
+
width="60"
|
|
125
|
+
height="38"
|
|
126
|
+
rx="10"
|
|
127
|
+
fill="#050811"
|
|
90
128
|
stroke="url(#bs_beam)"
|
|
91
|
-
strokeWidth="2"
|
|
129
|
+
strokeWidth="2.5"
|
|
92
130
|
/>
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
<Path d="
|
|
96
|
-
<Path d="
|
|
97
|
-
<Path d="M130 169 L126 185" stroke="#EC4899" />
|
|
131
|
+
<G strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" fill="none">
|
|
132
|
+
<Path d="M116 174 L108 181 L116 188" stroke="#38BDF8" />
|
|
133
|
+
<Path d="M140 174 L148 181 L140 188" stroke="#38BDF8" />
|
|
134
|
+
<Path d="M131 171 L125 191" stroke="#F43F5E" />
|
|
98
135
|
</G>
|
|
99
136
|
|
|
100
|
-
{/*
|
|
137
|
+
{/* ── 5. Facial Mask Plate ── */}
|
|
101
138
|
<Path
|
|
102
|
-
d="M128
|
|
103
|
-
fill="#
|
|
104
|
-
stroke="#
|
|
105
|
-
strokeWidth="2"
|
|
106
|
-
strokeOpacity={0.6}
|
|
139
|
+
d="M128 88 C152 64 192 72 192 104 C192 132 162 152 128 152 C94 152 64 132 64 104 C64 72 104 64 128 88 Z"
|
|
140
|
+
fill="#1E1B4B"
|
|
141
|
+
stroke="url(#bs_beam)"
|
|
142
|
+
strokeWidth="2.8"
|
|
107
143
|
/>
|
|
108
144
|
|
|
109
|
-
{/* Right Eye (
|
|
110
|
-
<Circle cx="
|
|
111
|
-
<Circle cx="
|
|
112
|
-
<Circle cx="
|
|
113
|
-
<Circle cx="
|
|
145
|
+
{/* ── 6. Right Eye (Glowing Owl Eye) ── */}
|
|
146
|
+
<Circle cx="156" cy="106" r="19" fill="url(#bs_iris)" stroke="#0F172A" strokeWidth="2.5" />
|
|
147
|
+
<Circle cx="156" cy="106" r="9.5" fill="#0B0F19" />
|
|
148
|
+
<Circle cx="159.5" cy="102.5" r="3.5" fill="#FFFFFF" />
|
|
149
|
+
<Circle cx="153" cy="109.5" r="1.8" fill="#FFFFFF" opacity={0.85} />
|
|
150
|
+
|
|
151
|
+
{/* ── 7. Left Eye (Diagnostic Magnifier Lens) ── */}
|
|
152
|
+
{/* Magnifier Glass Glow */}
|
|
153
|
+
<Circle cx="94" cy="104" r="30" fill="url(#bs_lens)" stroke="url(#bs_beam)" strokeWidth="6" />
|
|
154
|
+
<Line x1="72" y1="126" x2="48" y2="152" stroke="#0B0F19" strokeWidth="13" strokeLinecap="round" />
|
|
155
|
+
<Line x1="72" y1="126" x2="48" y2="152" stroke="url(#bs_beam)" strokeWidth="8" strokeLinecap="round" />
|
|
114
156
|
|
|
115
|
-
{/*
|
|
116
|
-
<Circle cx="
|
|
117
|
-
<Circle cx="
|
|
118
|
-
<Circle cx="
|
|
119
|
-
<Circle cx="
|
|
157
|
+
{/* Eye Inside Magnifier */}
|
|
158
|
+
<Circle cx="94" cy="104" r="21" fill="url(#bs_iris)" stroke="#0F172A" strokeWidth="2.5" />
|
|
159
|
+
<Circle cx="94" cy="104" r="10.5" fill="#0B0F19" />
|
|
160
|
+
<Circle cx="98" cy="100" r="4" fill="#FFFFFF" />
|
|
161
|
+
<Circle cx="90.5" cy="107.5" r="2" fill="#FFFFFF" opacity={0.85} />
|
|
120
162
|
|
|
121
|
-
{/*
|
|
122
|
-
<
|
|
123
|
-
|
|
124
|
-
|
|
163
|
+
{/* Lens Reflection Highlight */}
|
|
164
|
+
<Path
|
|
165
|
+
d="M74 94 A26 26 0 0 1 106 78"
|
|
166
|
+
stroke="#FFFFFF"
|
|
167
|
+
strokeWidth="3"
|
|
168
|
+
strokeLinecap="round"
|
|
169
|
+
opacity={0.65}
|
|
170
|
+
fill="none"
|
|
171
|
+
/>
|
|
125
172
|
|
|
126
|
-
{/* Beak */}
|
|
173
|
+
{/* ── 8. Beak ── */}
|
|
127
174
|
<Path
|
|
128
|
-
d="M123
|
|
175
|
+
d="M123 120 Q128 118 133 120 Q131.5 133 128 137 Q124.5 133 123 120 Z"
|
|
129
176
|
fill="url(#bs_beak)"
|
|
177
|
+
stroke="#78350F"
|
|
178
|
+
strokeWidth="1"
|
|
130
179
|
/>
|
|
131
180
|
</Svg>
|
|
132
181
|
);
|
|
@@ -12,7 +12,21 @@ import {EmptyRadarIcon} from './NetworkIcons';
|
|
|
12
12
|
import {AppColors} from '../styles/AppColors';
|
|
13
13
|
import styles from '../styles';
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
interface EmptyStateProps {
|
|
16
|
+
isSearch?: boolean;
|
|
17
|
+
searchQuery?: string;
|
|
18
|
+
customTitle?: string;
|
|
19
|
+
customSub?: string;
|
|
20
|
+
onClearSearch?: () => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const EmptyState = React.memo(function EmptyState({
|
|
24
|
+
isSearch,
|
|
25
|
+
searchQuery,
|
|
26
|
+
customTitle,
|
|
27
|
+
customSub,
|
|
28
|
+
onClearSearch,
|
|
29
|
+
}: EmptyStateProps) {
|
|
16
30
|
const iconPulse = useRef(new Animated.Value(1)).current;
|
|
17
31
|
|
|
18
32
|
useEffect(() => {
|
|
@@ -54,13 +68,21 @@ const EmptyState = React.memo(function EmptyState({isSearch}: {isSearch?: boolea
|
|
|
54
68
|
<EmptyRadarIcon color={AppColors.purple} size={32} />
|
|
55
69
|
</Animated.View>
|
|
56
70
|
<Text style={styles.emptyTitle}>
|
|
57
|
-
{isSearch ? 'No matching
|
|
71
|
+
{customTitle || (isSearch ? 'No matching results' : 'No network activity')}
|
|
58
72
|
</Text>
|
|
59
73
|
<Text style={styles.emptySub}>
|
|
60
|
-
{
|
|
61
|
-
|
|
62
|
-
|
|
74
|
+
{customSub ||
|
|
75
|
+
(isSearch
|
|
76
|
+
? searchQuery
|
|
77
|
+
? `No items matched "${searchQuery}"`
|
|
78
|
+
: 'Try adjusting your filters or search keywords.'
|
|
79
|
+
: 'Listening for incoming API calls...')}
|
|
63
80
|
</Text>
|
|
81
|
+
{isSearch && onClearSearch && (
|
|
82
|
+
<TouchableScale style={styles.reloadBtn} onPress={onClearSearch}>
|
|
83
|
+
<Text style={styles.reloadBtnText}>Clear Search & Filters</Text>
|
|
84
|
+
</TouchableScale>
|
|
85
|
+
)}
|
|
64
86
|
{!isSearch && (
|
|
65
87
|
<TouchableScale style={styles.reloadBtn} onPress={handleReload}>
|
|
66
88
|
<Text style={styles.reloadBtnText}>Reload App</Text>
|