react-native-inapp-inspector 1.1.11 → 1.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commonjs/components/AnalyticsDetail.js +93 -479
- package/dist/commonjs/components/AnalyticsEventCard.js +25 -25
- package/dist/commonjs/components/ConsoleLogCard.js +3 -1
- package/dist/commonjs/components/HighlightText.js +1 -1
- package/dist/commonjs/components/JsonViewer.d.ts +3 -1
- package/dist/commonjs/components/JsonViewer.js +327 -9
- package/dist/commonjs/components/MetaAccordion.d.ts +10 -1
- package/dist/commonjs/components/MetaAccordion.js +121 -24
- package/dist/commonjs/components/NetworkIcons.d.ts +1 -0
- package/dist/commonjs/components/NetworkIcons.js +8 -1
- package/dist/commonjs/components/ReduxTreeView.d.ts +12 -17
- package/dist/commonjs/components/ReduxTreeView.js +1045 -632
- package/dist/commonjs/components/SectionHeader.d.ts +1 -1
- package/dist/commonjs/components/SectionHeader.js +7 -1
- package/dist/commonjs/components/TouchableScale.js +8 -0
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/reduxLogger.d.ts +2 -0
- package/dist/commonjs/customHooks/reduxLogger.js +2 -0
- package/dist/commonjs/helpers/index.d.ts +3 -0
- package/dist/commonjs/helpers/index.js +103 -1
- package/dist/commonjs/helpers/settingsStore.d.ts +1 -0
- package/dist/commonjs/helpers/settingsStore.js +4 -0
- package/dist/commonjs/index.js +385 -339
- package/dist/commonjs/types/index.d.ts +3 -0
- package/dist/esm/components/AnalyticsDetail.js +94 -480
- package/dist/esm/components/AnalyticsEventCard.js +25 -25
- package/dist/esm/components/ConsoleLogCard.js +3 -1
- package/dist/esm/components/HighlightText.js +3 -3
- package/dist/esm/components/JsonViewer.d.ts +3 -1
- package/dist/esm/components/JsonViewer.js +295 -10
- package/dist/esm/components/MetaAccordion.d.ts +10 -1
- package/dist/esm/components/MetaAccordion.js +90 -26
- package/dist/esm/components/NetworkIcons.d.ts +1 -0
- package/dist/esm/components/NetworkIcons.js +6 -0
- package/dist/esm/components/ReduxTreeView.d.ts +12 -17
- package/dist/esm/components/ReduxTreeView.js +1047 -629
- package/dist/esm/components/SectionHeader.d.ts +1 -1
- package/dist/esm/components/SectionHeader.js +8 -2
- package/dist/esm/components/TouchableScale.js +9 -1
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/reduxLogger.d.ts +2 -0
- package/dist/esm/customHooks/reduxLogger.js +2 -0
- package/dist/esm/helpers/index.d.ts +3 -0
- package/dist/esm/helpers/index.js +100 -1
- package/dist/esm/helpers/settingsStore.d.ts +1 -0
- package/dist/esm/helpers/settingsStore.js +3 -0
- package/dist/esm/index.js +389 -343
- package/dist/esm/types/index.d.ts +3 -0
- package/example/package-lock.json +33 -74
- package/example/package.json +1 -1
- package/package.json +1 -1
package/dist/esm/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useMemo, useRef, useState, useCallback } from 'react';
|
|
2
|
-
import { Alert, Animated, StyleSheet, FlatList,
|
|
2
|
+
import { Alert, Animated, StyleSheet, FlatList, Modal, PanResponder, Platform, Pressable, ScrollView, Text, TextInput, View, Linking, Image, InteractionManager, ActivityIndicator, StatusBar, TouchableOpacity, UIManager, LogBox, } from 'react-native';
|
|
3
3
|
import Svg, { Circle, Path } from 'react-native-svg';
|
|
4
4
|
import LinearGradient from 'react-native-linear-gradient';
|
|
5
5
|
import { useNavigationState, NavigationContext } from '@react-navigation/native';
|
|
@@ -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,
|
|
14
|
+
import { ReduxTreeView, } from './components/ReduxTreeView';
|
|
15
15
|
import DomainHeader from './components/DomainHeader';
|
|
16
16
|
import DiffViewer from './components/DiffViewer';
|
|
17
17
|
import LogCard from './components/LogCard';
|
|
@@ -22,11 +22,11 @@ import HighlightText from './components/HighlightText';
|
|
|
22
22
|
import CodeSnippet from './components/CodeSnippet';
|
|
23
23
|
import AnimatedEntrance from './components/AnimatedEntrance';
|
|
24
24
|
// Helpers
|
|
25
|
-
import { formatDateTime, getStatusColor, getNavigationInfo, deduplicateLogs, getDomainColor, formatDisplayUrl, getFetchCommand, getCurlCommand, getSize, } from './helpers';
|
|
25
|
+
import { formatDateTime, getStatusColor, getNavigationInfo, deduplicateLogs, getDomainColor, formatDisplayUrl, getFetchCommand, getCurlCommand, getSize, getBundleIdentifier, getAppName, } from './helpers';
|
|
26
26
|
// #5 — settings persistence
|
|
27
27
|
import { loadSettings, saveSettings, setCustomStorage, isPersistentStorageAvailable, clearPersistedSettings, } from './helpers/settingsStore';
|
|
28
28
|
// Assets
|
|
29
|
-
import { EmptyRadarIcon, FailIcon, SearchIcon, ScreenIcon, ClearIcon, SortArrowIcon, FilterIcon, InsightsIcon, GlobeIcon, DownloadIcon, CloseWhite, TrashIcon, WhiteBackNavigation, TerminalIcon, SignalIcon, AnalyticsIcon, SunIcon, MoonIcon, BrandCircleIcon,
|
|
29
|
+
import { EmptyRadarIcon, FailIcon, SearchIcon, ScreenIcon, ClearIcon, SortArrowIcon, FilterIcon, InsightsIcon, GlobeIcon, DownloadIcon, CloseWhite, TrashIcon, WhiteBackNavigation, TerminalIcon, SignalIcon, AnalyticsIcon, SunIcon, MoonIcon, BrandCircleIcon, HtmlIcon, CssIcon, JsIcon, ClockIcon, EyeIcon, CheckIcon, SettingsIcon, RequestIcon, ResponseIcon, HeadersIcon, StatusIcon, ChevronIcon, WipeIcon, LayersIcon, UserIcon, InfoCircleIcon, WarningTriangleIcon, ErrorCircleIcon, TrendingUpIcon, MotionIcon, } from './components/NetworkIcons';
|
|
30
30
|
import ErrorBoundary from './components/ErrorBoundary';
|
|
31
31
|
// Stylesheet
|
|
32
32
|
import { AppColors } from './styles/AppColors';
|
|
@@ -111,7 +111,8 @@ const NavigationTracker = ({ onStateChange }) => {
|
|
|
111
111
|
return null;
|
|
112
112
|
};
|
|
113
113
|
const animateNextLayout = () => {
|
|
114
|
-
LayoutAnimation
|
|
114
|
+
// Disabled LayoutAnimation to prevent iOS NSRangeException crashes under Fabric
|
|
115
|
+
// and Android rendering performance freezes.
|
|
115
116
|
};
|
|
116
117
|
const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
|
|
117
118
|
// Set custom storage synchronously during render phase
|
|
@@ -135,7 +136,6 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
|
|
|
135
136
|
const [search, setSearch] = useState('');
|
|
136
137
|
const [detailSearch, setDetailSearch] = useState('');
|
|
137
138
|
const [reduxSearch, setReduxSearch] = useState('');
|
|
138
|
-
const [reduxActiveSubTab, setReduxActiveSubTab] = useState('timeline');
|
|
139
139
|
const [apiDetailActiveTab, setApiDetailActiveTab] = useState('response');
|
|
140
140
|
useEffect(() => {
|
|
141
141
|
LogBox.ignoreAllLogs(enabled);
|
|
@@ -154,6 +154,7 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
|
|
|
154
154
|
const [sectionFilters, setSectionFilters] = useState({});
|
|
155
155
|
const [collapsedSections, setCollapsedSections] = useState(new Set());
|
|
156
156
|
const [showNetworkMenu, setShowNetworkMenu] = useState(false);
|
|
157
|
+
const [showHeaderInfo, setShowHeaderInfo] = useState(false);
|
|
157
158
|
const [showUiMenu, setShowUiMenu] = useState(false);
|
|
158
159
|
const [sortOrder, setSortOrder] = useState('newest');
|
|
159
160
|
// #7 — sort order for the Logs (console) tab
|
|
@@ -193,7 +194,7 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
|
|
|
193
194
|
const [maxConsoleLogs, setMaxConsoleLogs] = useState(200);
|
|
194
195
|
const [showConsoleLevels, setShowConsoleLevels] = useState({
|
|
195
196
|
info: true,
|
|
196
|
-
warn:
|
|
197
|
+
warn: false,
|
|
197
198
|
error: true,
|
|
198
199
|
});
|
|
199
200
|
const visibleConsoleLogs = useMemo(() => {
|
|
@@ -702,7 +703,13 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
|
|
|
702
703
|
const task = InteractionManager.runAfterInteractions(() => {
|
|
703
704
|
setIsReady(true);
|
|
704
705
|
});
|
|
705
|
-
|
|
706
|
+
const fallbackTimer = setTimeout(() => {
|
|
707
|
+
setIsReady(true);
|
|
708
|
+
}, 350);
|
|
709
|
+
return () => {
|
|
710
|
+
task.cancel();
|
|
711
|
+
clearTimeout(fallbackTimer);
|
|
712
|
+
};
|
|
706
713
|
}
|
|
707
714
|
else {
|
|
708
715
|
setIsReady(false);
|
|
@@ -715,9 +722,10 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
|
|
|
715
722
|
setupConsoleLogger();
|
|
716
723
|
autoSetupAnalyticsLogger();
|
|
717
724
|
let timeoutId;
|
|
725
|
+
let isFirstNetworkCall = true;
|
|
718
726
|
const unsubscribe = subscribeNetworkLogs((raw) => {
|
|
719
727
|
clearTimeout(timeoutId);
|
|
720
|
-
|
|
728
|
+
const updateNetworkState = () => {
|
|
721
729
|
const deduped = deduplicateLogs(raw);
|
|
722
730
|
const incoming = new Set(deduped.map(l => l.id));
|
|
723
731
|
const freshIds = new Set();
|
|
@@ -736,13 +744,24 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
|
|
|
736
744
|
setTimeout(() => setNewLogIds(new Set()), 1200);
|
|
737
745
|
}
|
|
738
746
|
setLogs(deduped);
|
|
739
|
-
}
|
|
747
|
+
};
|
|
748
|
+
if (isFirstNetworkCall) {
|
|
749
|
+
isFirstNetworkCall = false;
|
|
750
|
+
const deduped = deduplicateLogs(raw);
|
|
751
|
+
const incoming = new Set(deduped.map(l => l.id));
|
|
752
|
+
prevLogIdsRef.current = incoming;
|
|
753
|
+
setLogs(deduped);
|
|
754
|
+
}
|
|
755
|
+
else {
|
|
756
|
+
timeoutId = setTimeout(updateNetworkState, 250);
|
|
757
|
+
}
|
|
740
758
|
});
|
|
741
759
|
// ─── Analytics subscription ──────────────────────────────────────────────
|
|
742
760
|
let analyticsTimeoutId;
|
|
761
|
+
let isFirstAnalyticsCall = true;
|
|
743
762
|
const unsubscribeAnalytics = subscribeAnalyticsEvents((raw) => {
|
|
744
763
|
clearTimeout(analyticsTimeoutId);
|
|
745
|
-
|
|
764
|
+
const updateAnalyticsState = () => {
|
|
746
765
|
const incoming = new Set(raw.map(e => e.id));
|
|
747
766
|
const freshIds = new Set();
|
|
748
767
|
incoming.forEach(id => {
|
|
@@ -760,15 +779,31 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
|
|
|
760
779
|
setTimeout(() => setNewEventIds(new Set()), 1200);
|
|
761
780
|
}
|
|
762
781
|
setAnalyticsEvents(raw);
|
|
763
|
-
}
|
|
782
|
+
};
|
|
783
|
+
if (isFirstAnalyticsCall) {
|
|
784
|
+
isFirstAnalyticsCall = false;
|
|
785
|
+
const incoming = new Set(raw.map(e => e.id));
|
|
786
|
+
prevEventIdsRef.current = incoming;
|
|
787
|
+
setAnalyticsEvents(raw);
|
|
788
|
+
}
|
|
789
|
+
else {
|
|
790
|
+
analyticsTimeoutId = setTimeout(updateAnalyticsState, 200);
|
|
791
|
+
}
|
|
764
792
|
});
|
|
765
793
|
// ─── Console subscription ────────────────────────────────────────────────
|
|
766
794
|
let consoleTimeoutId;
|
|
795
|
+
let isFirstConsoleCall = true;
|
|
767
796
|
const unsubscribeConsole = subscribeConsoleLogs((raw) => {
|
|
768
797
|
clearTimeout(consoleTimeoutId);
|
|
769
|
-
|
|
798
|
+
if (isFirstConsoleCall) {
|
|
799
|
+
isFirstConsoleCall = false;
|
|
770
800
|
setConsoleLogs(raw);
|
|
771
|
-
}
|
|
801
|
+
}
|
|
802
|
+
else {
|
|
803
|
+
consoleTimeoutId = setTimeout(() => {
|
|
804
|
+
setConsoleLogs(raw);
|
|
805
|
+
}, 200);
|
|
806
|
+
}
|
|
772
807
|
});
|
|
773
808
|
setWebViewLogs(getWebViewLogs());
|
|
774
809
|
setWebViewNavHistory(getWebViewNavHistory());
|
|
@@ -778,24 +813,34 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
|
|
|
778
813
|
setWebViewHtmlUrl(getWebViewHtmlUrl());
|
|
779
814
|
// ─── WebView subscription ────────────────────────────────────────────────
|
|
780
815
|
let webViewTimeoutId;
|
|
816
|
+
let isFirstWebViewCall = true;
|
|
781
817
|
const unsubscribeWebView = subscribeWebView(() => {
|
|
782
818
|
clearTimeout(webViewTimeoutId);
|
|
783
|
-
|
|
819
|
+
const updateWebViewState = () => {
|
|
784
820
|
setWebViewLogs(getWebViewLogs());
|
|
785
821
|
setWebViewNavHistory(getWebViewNavHistory());
|
|
786
822
|
setWebViewHtml(getWebViewHtml());
|
|
787
823
|
setWebViewCss(getWebViewCss());
|
|
788
824
|
setWebViewJs(getWebViewJs());
|
|
789
825
|
setWebViewHtmlUrl(getWebViewHtmlUrl());
|
|
790
|
-
}
|
|
826
|
+
};
|
|
827
|
+
if (isFirstWebViewCall) {
|
|
828
|
+
isFirstWebViewCall = false;
|
|
829
|
+
updateWebViewState();
|
|
830
|
+
}
|
|
831
|
+
else {
|
|
832
|
+
webViewTimeoutId = setTimeout(updateWebViewState, 200);
|
|
833
|
+
}
|
|
791
834
|
});
|
|
792
|
-
|
|
835
|
+
const initialReduxState = getReduxState();
|
|
836
|
+
setReduxState(initialReduxState && typeof initialReduxState === 'object' ? { ...initialReduxState } : initialReduxState);
|
|
793
837
|
setReduxActionHistory([...getActionHistory()]);
|
|
794
838
|
setReduxLastActionMap({ ...getLastActionForReducer() });
|
|
795
839
|
const unsubscribeRedux = subscribeReduxState(() => {
|
|
796
840
|
// New references each time guarantee the Redux tab updates live, even when
|
|
797
841
|
// the root state object reference is unchanged or auto-refresh is paused.
|
|
798
|
-
|
|
842
|
+
const freshState = getReduxState();
|
|
843
|
+
setReduxState(freshState && typeof freshState === 'object' ? { ...freshState } : freshState);
|
|
799
844
|
setReduxActionHistory([...getActionHistory()]);
|
|
800
845
|
setReduxLastActionMap({ ...getLastActionForReducer() });
|
|
801
846
|
});
|
|
@@ -2106,6 +2151,97 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
|
|
|
2106
2151
|
</TouchableScale>
|
|
2107
2152
|
</View>
|
|
2108
2153
|
|
|
2154
|
+
{/* Divider */}
|
|
2155
|
+
<View style={{
|
|
2156
|
+
height: 1,
|
|
2157
|
+
backgroundColor: AppColors.dividerColor,
|
|
2158
|
+
}}/>
|
|
2159
|
+
|
|
2160
|
+
{/* Logs Console Levels */}
|
|
2161
|
+
<View style={{
|
|
2162
|
+
paddingVertical: 12,
|
|
2163
|
+
paddingHorizontal: 14,
|
|
2164
|
+
}}>
|
|
2165
|
+
<View style={{
|
|
2166
|
+
flexDirection: 'row',
|
|
2167
|
+
alignItems: 'center',
|
|
2168
|
+
gap: 8,
|
|
2169
|
+
}}>
|
|
2170
|
+
<View style={{
|
|
2171
|
+
width: 20,
|
|
2172
|
+
height: 20,
|
|
2173
|
+
borderRadius: 6,
|
|
2174
|
+
backgroundColor: AppColors.purpleShade50,
|
|
2175
|
+
borderWidth: 1,
|
|
2176
|
+
borderColor: 'rgba(104,75,155,0.2)',
|
|
2177
|
+
alignItems: 'center',
|
|
2178
|
+
justifyContent: 'center',
|
|
2179
|
+
}}>
|
|
2180
|
+
<TerminalIcon color={AppColors.purple} size={11}/>
|
|
2181
|
+
</View>
|
|
2182
|
+
<View style={{ flex: 1 }}>
|
|
2183
|
+
<Text style={{
|
|
2184
|
+
fontFamily: AppFonts.interBold,
|
|
2185
|
+
fontSize: 13,
|
|
2186
|
+
color: AppColors.primaryBlack,
|
|
2187
|
+
}}>
|
|
2188
|
+
Logs Console Levels
|
|
2189
|
+
</Text>
|
|
2190
|
+
<Text style={{
|
|
2191
|
+
fontFamily: AppFonts.interRegular,
|
|
2192
|
+
fontSize: 11,
|
|
2193
|
+
color: AppColors.grayText,
|
|
2194
|
+
marginTop: 1,
|
|
2195
|
+
}}>
|
|
2196
|
+
Toggle which log levels are visible in the Logs tab
|
|
2197
|
+
</Text>
|
|
2198
|
+
</View>
|
|
2199
|
+
</View>
|
|
2200
|
+
|
|
2201
|
+
<View style={{
|
|
2202
|
+
flexDirection: 'row',
|
|
2203
|
+
gap: 8,
|
|
2204
|
+
marginTop: 10,
|
|
2205
|
+
}}>
|
|
2206
|
+
{([
|
|
2207
|
+
{ key: 'info', label: 'Info', color: '#3B82F6' },
|
|
2208
|
+
{ key: 'warn', label: 'Warning', color: '#F59E0B' },
|
|
2209
|
+
{ key: 'error', label: 'Error', color: '#EF4444' },
|
|
2210
|
+
]).map(level => {
|
|
2211
|
+
const isActive = showConsoleLevels[level.key];
|
|
2212
|
+
return (<TouchableScale key={level.key} onPress={() => setShowConsoleLevels(prev => ({
|
|
2213
|
+
...prev,
|
|
2214
|
+
[level.key]: !prev[level.key],
|
|
2215
|
+
}))} style={{
|
|
2216
|
+
flex: 1,
|
|
2217
|
+
flexDirection: 'row',
|
|
2218
|
+
alignItems: 'center',
|
|
2219
|
+
justifyContent: 'center',
|
|
2220
|
+
gap: 6,
|
|
2221
|
+
paddingVertical: 8,
|
|
2222
|
+
borderRadius: 8,
|
|
2223
|
+
borderWidth: 1.5,
|
|
2224
|
+
borderColor: isActive ? level.color : AppColors.grayBorderSecondary,
|
|
2225
|
+
backgroundColor: isActive ? `${level.color}0D` : AppColors.primaryLight,
|
|
2226
|
+
}}>
|
|
2227
|
+
<View style={{
|
|
2228
|
+
width: 8,
|
|
2229
|
+
height: 8,
|
|
2230
|
+
borderRadius: 4,
|
|
2231
|
+
backgroundColor: isActive ? level.color : AppColors.grayBorderSecondary,
|
|
2232
|
+
}}/>
|
|
2233
|
+
<Text style={{
|
|
2234
|
+
fontFamily: AppFonts.interBold,
|
|
2235
|
+
fontSize: 11,
|
|
2236
|
+
color: isActive ? level.color : AppColors.grayText,
|
|
2237
|
+
}}>
|
|
2238
|
+
{level.label}
|
|
2239
|
+
</Text>
|
|
2240
|
+
</TouchableScale>);
|
|
2241
|
+
})}
|
|
2242
|
+
</View>
|
|
2243
|
+
</View>
|
|
2244
|
+
|
|
2109
2245
|
{/* Divider */}
|
|
2110
2246
|
<View style={{
|
|
2111
2247
|
height: 1,
|
|
@@ -3435,129 +3571,8 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
|
|
|
3435
3571
|
<Text style={styles.emptySub}>Connected store state is empty.</Text>
|
|
3436
3572
|
</View>);
|
|
3437
3573
|
}
|
|
3438
|
-
// Build hierarchical tree: Store -> Reducers -> Action -> Data.
|
|
3439
|
-
// These come from component state (refreshed on every dispatch) so the view stays live.
|
|
3440
3574
|
const lastActionMap = reduxLastActionMap;
|
|
3441
|
-
const actionHistory = reduxActionHistory;
|
|
3442
3575
|
return (<ScrollView style={styles.detailScroll} contentContainerStyle={{ paddingBottom: 24 }}>
|
|
3443
|
-
{/* Tab View Selection Segments */}
|
|
3444
|
-
<View style={{
|
|
3445
|
-
flexDirection: 'row',
|
|
3446
|
-
backgroundColor: AppColors.grayBackground,
|
|
3447
|
-
borderRadius: 10,
|
|
3448
|
-
padding: 3,
|
|
3449
|
-
marginHorizontal: 16,
|
|
3450
|
-
marginTop: 12,
|
|
3451
|
-
marginBottom: 12,
|
|
3452
|
-
borderWidth: 1,
|
|
3453
|
-
borderColor: AppColors.dividerColor,
|
|
3454
|
-
}}>
|
|
3455
|
-
<TouchableOpacity onPress={() => {
|
|
3456
|
-
animateNextLayout();
|
|
3457
|
-
setReduxActiveSubTab('timeline');
|
|
3458
|
-
}} style={{
|
|
3459
|
-
flex: 1,
|
|
3460
|
-
paddingVertical: 6,
|
|
3461
|
-
alignItems: 'center',
|
|
3462
|
-
justifyContent: 'center',
|
|
3463
|
-
borderRadius: 8,
|
|
3464
|
-
backgroundColor: reduxActiveSubTab === 'timeline'
|
|
3465
|
-
? AppColors.purple
|
|
3466
|
-
: 'transparent',
|
|
3467
|
-
}}>
|
|
3468
|
-
<View style={{
|
|
3469
|
-
flexDirection: 'row',
|
|
3470
|
-
alignItems: 'center',
|
|
3471
|
-
justifyContent: 'center',
|
|
3472
|
-
gap: 6,
|
|
3473
|
-
}}>
|
|
3474
|
-
<ReduxTimelineIcon color={reduxActiveSubTab === 'timeline'
|
|
3475
|
-
? '#FFFFFF'
|
|
3476
|
-
: AppColors.grayText} size={13}/>
|
|
3477
|
-
<Text style={{
|
|
3478
|
-
fontFamily: AppFonts.interBold,
|
|
3479
|
-
fontSize: 11,
|
|
3480
|
-
color: reduxActiveSubTab === 'timeline'
|
|
3481
|
-
? '#FFFFFF'
|
|
3482
|
-
: AppColors.grayText,
|
|
3483
|
-
}}>
|
|
3484
|
-
Action Timeline
|
|
3485
|
-
</Text>
|
|
3486
|
-
<View style={{
|
|
3487
|
-
minWidth: 18,
|
|
3488
|
-
paddingHorizontal: 5,
|
|
3489
|
-
height: 16,
|
|
3490
|
-
borderRadius: 8,
|
|
3491
|
-
alignItems: 'center',
|
|
3492
|
-
justifyContent: 'center',
|
|
3493
|
-
backgroundColor: reduxActiveSubTab === 'timeline'
|
|
3494
|
-
? 'rgba(255,255,255,0.28)'
|
|
3495
|
-
: AppColors.dividerColor,
|
|
3496
|
-
}}>
|
|
3497
|
-
<Text style={{
|
|
3498
|
-
fontFamily: AppFonts.interBold,
|
|
3499
|
-
fontSize: 9,
|
|
3500
|
-
color: reduxActiveSubTab === 'timeline'
|
|
3501
|
-
? '#FFFFFF'
|
|
3502
|
-
: AppColors.grayText,
|
|
3503
|
-
}}>
|
|
3504
|
-
{actionHistory.length}
|
|
3505
|
-
</Text>
|
|
3506
|
-
</View>
|
|
3507
|
-
</View>
|
|
3508
|
-
</TouchableOpacity>
|
|
3509
|
-
<TouchableOpacity onPress={() => {
|
|
3510
|
-
animateNextLayout();
|
|
3511
|
-
setReduxActiveSubTab('tree');
|
|
3512
|
-
}} style={{
|
|
3513
|
-
flex: 1,
|
|
3514
|
-
paddingVertical: 6,
|
|
3515
|
-
alignItems: 'center',
|
|
3516
|
-
justifyContent: 'center',
|
|
3517
|
-
borderRadius: 8,
|
|
3518
|
-
backgroundColor: reduxActiveSubTab === 'tree' ? AppColors.purple : 'transparent',
|
|
3519
|
-
}}>
|
|
3520
|
-
<View style={{
|
|
3521
|
-
flexDirection: 'row',
|
|
3522
|
-
alignItems: 'center',
|
|
3523
|
-
justifyContent: 'center',
|
|
3524
|
-
gap: 6,
|
|
3525
|
-
}}>
|
|
3526
|
-
<ReduxTreeIcon color={reduxActiveSubTab === 'tree' ? '#FFFFFF' : AppColors.grayText} size={13}/>
|
|
3527
|
-
<Text style={{
|
|
3528
|
-
fontFamily: AppFonts.interBold,
|
|
3529
|
-
fontSize: 11,
|
|
3530
|
-
color: reduxActiveSubTab === 'tree'
|
|
3531
|
-
? '#FFFFFF'
|
|
3532
|
-
: AppColors.grayText,
|
|
3533
|
-
}}>
|
|
3534
|
-
Store Tree
|
|
3535
|
-
</Text>
|
|
3536
|
-
<View style={{
|
|
3537
|
-
minWidth: 18,
|
|
3538
|
-
paddingHorizontal: 5,
|
|
3539
|
-
height: 16,
|
|
3540
|
-
borderRadius: 8,
|
|
3541
|
-
alignItems: 'center',
|
|
3542
|
-
justifyContent: 'center',
|
|
3543
|
-
backgroundColor: reduxActiveSubTab === 'tree'
|
|
3544
|
-
? 'rgba(255,255,255,0.28)'
|
|
3545
|
-
: AppColors.dividerColor,
|
|
3546
|
-
}}>
|
|
3547
|
-
<Text style={{
|
|
3548
|
-
fontFamily: AppFonts.interBold,
|
|
3549
|
-
fontSize: 9,
|
|
3550
|
-
color: reduxActiveSubTab === 'tree'
|
|
3551
|
-
? '#FFFFFF'
|
|
3552
|
-
: AppColors.grayText,
|
|
3553
|
-
}}>
|
|
3554
|
-
{reducerKeys.length}
|
|
3555
|
-
</Text>
|
|
3556
|
-
</View>
|
|
3557
|
-
</View>
|
|
3558
|
-
</TouchableOpacity>
|
|
3559
|
-
</View>
|
|
3560
|
-
|
|
3561
3576
|
{/* Search Bar */}
|
|
3562
3577
|
<View style={{
|
|
3563
3578
|
flexDirection: 'row',
|
|
@@ -3565,15 +3580,14 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
|
|
|
3565
3580
|
backgroundColor: AppColors.grayBackground,
|
|
3566
3581
|
borderRadius: 8,
|
|
3567
3582
|
marginHorizontal: 16,
|
|
3583
|
+
marginTop: 16,
|
|
3568
3584
|
marginBottom: 12,
|
|
3569
3585
|
paddingHorizontal: 10,
|
|
3570
3586
|
borderWidth: 1,
|
|
3571
3587
|
borderColor: AppColors.dividerColor,
|
|
3572
3588
|
height: 36,
|
|
3573
3589
|
}}>
|
|
3574
|
-
<TextInput placeholder={
|
|
3575
|
-
? 'Search actions or payloads...'
|
|
3576
|
-
: 'Search Redux keys or values...'} placeholderTextColor={AppColors.grayTextWeak} value={reduxSearch} onChangeText={setReduxSearch} style={{
|
|
3590
|
+
<TextInput placeholder="Search Redux keys or values..." placeholderTextColor={AppColors.grayTextWeak} value={reduxSearch} onChangeText={setReduxSearch} style={{
|
|
3577
3591
|
flex: 1,
|
|
3578
3592
|
fontFamily: AppFonts.interRegular,
|
|
3579
3593
|
fontSize: 12,
|
|
@@ -3594,7 +3608,7 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
|
|
|
3594
3608
|
marginHorizontal: 16,
|
|
3595
3609
|
padding: 12,
|
|
3596
3610
|
}}>
|
|
3597
|
-
|
|
3611
|
+
<ReduxTreeView state={reduxState} lastActionMap={lastActionMap} search={reduxSearch}/>
|
|
3598
3612
|
</View>
|
|
3599
3613
|
</ScrollView>);
|
|
3600
3614
|
};
|
|
@@ -3698,16 +3712,16 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
|
|
|
3698
3712
|
<WhiteBackNavigation />
|
|
3699
3713
|
</TouchableScale>
|
|
3700
3714
|
|
|
3701
|
-
{selected == null && selectedEvent == null ? (<
|
|
3715
|
+
{selected == null && selectedEvent == null ? (<TouchableScale onPress={() => setShowHeaderInfo(prev => !prev)} style={{
|
|
3702
3716
|
flexDirection: 'row',
|
|
3703
3717
|
alignItems: 'center',
|
|
3704
|
-
gap:
|
|
3718
|
+
gap: 10,
|
|
3705
3719
|
flex: 1,
|
|
3706
3720
|
}}>
|
|
3707
3721
|
<View style={{
|
|
3708
|
-
width:
|
|
3709
|
-
height:
|
|
3710
|
-
borderRadius:
|
|
3722
|
+
width: 38,
|
|
3723
|
+
height: 38,
|
|
3724
|
+
borderRadius: 19,
|
|
3711
3725
|
backgroundColor: 'rgba(255,255,255,0.13)',
|
|
3712
3726
|
borderWidth: 1.5,
|
|
3713
3727
|
borderColor: 'rgba(255,255,255,0.25)',
|
|
@@ -3718,94 +3732,13 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
|
|
|
3718
3732
|
shadowRadius: 4,
|
|
3719
3733
|
shadowOffset: { width: 0, height: 2 },
|
|
3720
3734
|
}}>
|
|
3721
|
-
<
|
|
3735
|
+
<BrandCircleIcon size={34}/>
|
|
3722
3736
|
</View>
|
|
3723
|
-
<View style={{ gap:
|
|
3724
|
-
<
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
flexDirection: 'row',
|
|
3729
|
-
alignItems: 'center',
|
|
3730
|
-
gap: 6,
|
|
3731
|
-
}}>
|
|
3732
|
-
{/* OS chip */}
|
|
3733
|
-
<View style={{
|
|
3734
|
-
flexDirection: 'row',
|
|
3735
|
-
alignItems: 'center',
|
|
3736
|
-
borderRadius: 6,
|
|
3737
|
-
overflow: 'hidden',
|
|
3738
|
-
borderWidth: 1,
|
|
3739
|
-
borderColor: 'rgba(255,255,255,0.18)',
|
|
3740
|
-
}}>
|
|
3741
|
-
<View style={{
|
|
3742
|
-
paddingHorizontal: 5,
|
|
3743
|
-
paddingVertical: 2,
|
|
3744
|
-
backgroundColor: 'rgba(255,255,255,0.28)',
|
|
3745
|
-
}}>
|
|
3746
|
-
<Text style={{
|
|
3747
|
-
fontFamily: AppFonts.interBold,
|
|
3748
|
-
fontSize: 9,
|
|
3749
|
-
color: '#FFFFFF',
|
|
3750
|
-
letterSpacing: 0.3,
|
|
3751
|
-
}}>
|
|
3752
|
-
{Platform.OS === 'ios' ? 'iOS' : 'Android'}
|
|
3753
|
-
</Text>
|
|
3754
|
-
</View>
|
|
3755
|
-
<View style={{
|
|
3756
|
-
paddingHorizontal: 5,
|
|
3757
|
-
paddingVertical: 2,
|
|
3758
|
-
backgroundColor: 'rgba(255,255,255,0.12)',
|
|
3759
|
-
}}>
|
|
3760
|
-
<Text style={{
|
|
3761
|
-
fontFamily: AppFonts.interMedium,
|
|
3762
|
-
fontSize: 9.5,
|
|
3763
|
-
color: 'rgba(255,255,255,0.92)',
|
|
3764
|
-
}}>
|
|
3765
|
-
{String(Platform.Version)}
|
|
3766
|
-
</Text>
|
|
3767
|
-
</View>
|
|
3768
|
-
</View>
|
|
3769
|
-
|
|
3770
|
-
{/* npm chip */}
|
|
3771
|
-
<View style={{
|
|
3772
|
-
flexDirection: 'row',
|
|
3773
|
-
alignItems: 'center',
|
|
3774
|
-
borderRadius: 6,
|
|
3775
|
-
overflow: 'hidden',
|
|
3776
|
-
borderWidth: 1,
|
|
3777
|
-
borderColor: 'rgba(255,255,255,0.18)',
|
|
3778
|
-
}}>
|
|
3779
|
-
<View style={{
|
|
3780
|
-
paddingHorizontal: 5,
|
|
3781
|
-
paddingVertical: 2,
|
|
3782
|
-
backgroundColor: 'rgba(255,255,255,0.28)',
|
|
3783
|
-
}}>
|
|
3784
|
-
<Text style={{
|
|
3785
|
-
fontFamily: AppFonts.interBold,
|
|
3786
|
-
fontSize: 9,
|
|
3787
|
-
color: '#FFFFFF',
|
|
3788
|
-
letterSpacing: 0.3,
|
|
3789
|
-
}}>
|
|
3790
|
-
npm
|
|
3791
|
-
</Text>
|
|
3792
|
-
</View>
|
|
3793
|
-
<View style={{
|
|
3794
|
-
paddingHorizontal: 5,
|
|
3795
|
-
paddingVertical: 2,
|
|
3796
|
-
backgroundColor: 'rgba(255,255,255,0.12)',
|
|
3797
|
-
}}>
|
|
3798
|
-
<Text style={{
|
|
3799
|
-
fontFamily: AppFonts.interMedium,
|
|
3800
|
-
fontSize: 9.5,
|
|
3801
|
-
color: 'rgba(255,255,255,0.92)',
|
|
3802
|
-
}}>
|
|
3803
|
-
v{LIB_VERSION}
|
|
3804
|
-
</Text>
|
|
3805
|
-
</View>
|
|
3806
|
-
</View>
|
|
3807
|
-
|
|
3808
|
-
{/* #1 — pulsing dot when a newer version is on NPM */}
|
|
3737
|
+
<View style={{ gap: 2, flex: 1 }}>
|
|
3738
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
3739
|
+
<Text style={[styles.headerTitle]} numberOfLines={1}>
|
|
3740
|
+
{getAppName()}
|
|
3741
|
+
</Text>
|
|
3809
3742
|
{updateAvailable && (<Pressable hitSlop={10} onPress={() => Alert.alert('Update Available', `react-native-inapp-inspector v${latestNpmVersion} is available on NPM (installed: v${LIB_VERSION}).`, [
|
|
3810
3743
|
{ text: 'Later', style: 'cancel' },
|
|
3811
3744
|
{
|
|
@@ -3828,8 +3761,120 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
|
|
|
3828
3761
|
}}/>
|
|
3829
3762
|
</Pressable>)}
|
|
3830
3763
|
</View>
|
|
3764
|
+
<View style={{
|
|
3765
|
+
flexDirection: 'row',
|
|
3766
|
+
alignItems: 'center',
|
|
3767
|
+
alignSelf: 'flex-start',
|
|
3768
|
+
backgroundColor: 'rgba(255,255,255,0.1)',
|
|
3769
|
+
borderRadius: 10,
|
|
3770
|
+
paddingHorizontal: 8,
|
|
3771
|
+
paddingVertical: 3,
|
|
3772
|
+
gap: 5,
|
|
3773
|
+
borderWidth: 1,
|
|
3774
|
+
borderColor: 'rgba(255,255,255,0.15)',
|
|
3775
|
+
}}>
|
|
3776
|
+
<View style={{
|
|
3777
|
+
width: 6,
|
|
3778
|
+
height: 6,
|
|
3779
|
+
borderRadius: 3,
|
|
3780
|
+
backgroundColor: '#4ADE80',
|
|
3781
|
+
}}/>
|
|
3782
|
+
<Text style={{
|
|
3783
|
+
fontFamily: AppFonts.interMedium,
|
|
3784
|
+
fontSize: 10,
|
|
3785
|
+
color: 'rgba(255, 255, 255, 0.85)',
|
|
3786
|
+
letterSpacing: 0.2,
|
|
3787
|
+
}} numberOfLines={1}>
|
|
3788
|
+
{getBundleIdentifier()}
|
|
3789
|
+
</Text>
|
|
3790
|
+
<Animated.View style={{
|
|
3791
|
+
transform: [{ rotate: showHeaderInfo ? '180deg' : '0deg' }],
|
|
3792
|
+
marginLeft: 2,
|
|
3793
|
+
}}>
|
|
3794
|
+
<ChevronIcon color="rgba(255,255,255,0.6)" size={12}/>
|
|
3795
|
+
</Animated.View>
|
|
3796
|
+
</View>
|
|
3797
|
+
{showHeaderInfo && (<View style={{
|
|
3798
|
+
flexDirection: 'row',
|
|
3799
|
+
alignItems: 'center',
|
|
3800
|
+
gap: 6,
|
|
3801
|
+
marginTop: 4,
|
|
3802
|
+
}}>
|
|
3803
|
+
<View style={{
|
|
3804
|
+
flexDirection: 'row',
|
|
3805
|
+
alignItems: 'center',
|
|
3806
|
+
borderRadius: 6,
|
|
3807
|
+
overflow: 'hidden',
|
|
3808
|
+
borderWidth: 1,
|
|
3809
|
+
borderColor: 'rgba(255,255,255,0.18)',
|
|
3810
|
+
}}>
|
|
3811
|
+
<View style={{
|
|
3812
|
+
paddingHorizontal: 5,
|
|
3813
|
+
paddingVertical: 2,
|
|
3814
|
+
backgroundColor: 'rgba(255,255,255,0.28)',
|
|
3815
|
+
}}>
|
|
3816
|
+
<Text style={{
|
|
3817
|
+
fontFamily: AppFonts.interBold,
|
|
3818
|
+
fontSize: 9,
|
|
3819
|
+
color: '#FFFFFF',
|
|
3820
|
+
letterSpacing: 0.3,
|
|
3821
|
+
}}>
|
|
3822
|
+
{Platform.OS === 'ios' ? 'iOS' : 'Android'}
|
|
3823
|
+
</Text>
|
|
3824
|
+
</View>
|
|
3825
|
+
<View style={{
|
|
3826
|
+
paddingHorizontal: 5,
|
|
3827
|
+
paddingVertical: 2,
|
|
3828
|
+
backgroundColor: 'rgba(255,255,255,0.12)',
|
|
3829
|
+
}}>
|
|
3830
|
+
<Text style={{
|
|
3831
|
+
fontFamily: AppFonts.interMedium,
|
|
3832
|
+
fontSize: 9.5,
|
|
3833
|
+
color: 'rgba(255,255,255,0.92)',
|
|
3834
|
+
}}>
|
|
3835
|
+
{String(Platform.Version)}
|
|
3836
|
+
</Text>
|
|
3837
|
+
</View>
|
|
3838
|
+
</View>
|
|
3839
|
+
<View style={{
|
|
3840
|
+
flexDirection: 'row',
|
|
3841
|
+
alignItems: 'center',
|
|
3842
|
+
borderRadius: 6,
|
|
3843
|
+
overflow: 'hidden',
|
|
3844
|
+
borderWidth: 1,
|
|
3845
|
+
borderColor: 'rgba(255,255,255,0.18)',
|
|
3846
|
+
}}>
|
|
3847
|
+
<View style={{
|
|
3848
|
+
paddingHorizontal: 5,
|
|
3849
|
+
paddingVertical: 2,
|
|
3850
|
+
backgroundColor: 'rgba(255,255,255,0.28)',
|
|
3851
|
+
}}>
|
|
3852
|
+
<Text style={{
|
|
3853
|
+
fontFamily: AppFonts.interBold,
|
|
3854
|
+
fontSize: 9,
|
|
3855
|
+
color: '#FFFFFF',
|
|
3856
|
+
letterSpacing: 0.3,
|
|
3857
|
+
}}>
|
|
3858
|
+
npm
|
|
3859
|
+
</Text>
|
|
3860
|
+
</View>
|
|
3861
|
+
<View style={{
|
|
3862
|
+
paddingHorizontal: 5,
|
|
3863
|
+
paddingVertical: 2,
|
|
3864
|
+
backgroundColor: 'rgba(255,255,255,0.12)',
|
|
3865
|
+
}}>
|
|
3866
|
+
<Text style={{
|
|
3867
|
+
fontFamily: AppFonts.interMedium,
|
|
3868
|
+
fontSize: 9.5,
|
|
3869
|
+
color: 'rgba(255,255,255,0.92)',
|
|
3870
|
+
}}>
|
|
3871
|
+
v{LIB_VERSION}
|
|
3872
|
+
</Text>
|
|
3873
|
+
</View>
|
|
3874
|
+
</View>
|
|
3875
|
+
</View>)}
|
|
3831
3876
|
</View>
|
|
3832
|
-
</
|
|
3877
|
+
</TouchableScale>) : null}
|
|
3833
3878
|
</View>
|
|
3834
3879
|
|
|
3835
3880
|
<View style={styles.headerCenter}>
|
|
@@ -4111,14 +4156,6 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
|
|
|
4111
4156
|
</Pressable>)}
|
|
4112
4157
|
</View>
|
|
4113
4158
|
{analyticsSubTab === 'ga_events' && (<View style={styles.toolbarRight}>
|
|
4114
|
-
<TouchableScale style={[
|
|
4115
|
-
styles.toolbarBtn,
|
|
4116
|
-
!hideScreenView && styles.toolbarBtnActive,
|
|
4117
|
-
]} onPress={() => setHideScreenView(prev => !prev)} hitSlop={10}>
|
|
4118
|
-
<ScreenIcon color={!hideScreenView
|
|
4119
|
-
? AppColors.purple
|
|
4120
|
-
: AppColors.grayTextStrong} size={18}/>
|
|
4121
|
-
</TouchableScale>
|
|
4122
4159
|
<TouchableScale style={{
|
|
4123
4160
|
flexDirection: 'row',
|
|
4124
4161
|
alignItems: 'center',
|
|
@@ -4249,109 +4286,118 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
|
|
|
4249
4286
|
|
|
4250
4287
|
{isReady ? (activeTab === 'insights' ? (<ScrollView style={styles.insightsContainer} contentContainerStyle={styles.insightsContent} showsVerticalScrollIndicator={false}>
|
|
4251
4288
|
{renderInsightsDashboard()}
|
|
4252
|
-
</ScrollView>) : activeTab === 'analytics' ? (
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
<Svg width={14} height={14} viewBox="0 0 24 24" fill={color}>
|
|
4274
|
-
<Circle cx="12" cy="12" r="10" opacity="0.3"/>
|
|
4275
|
-
<Path d="M7 14l3-3 4 4 6-6" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
|
|
4276
|
-
</Svg>
|
|
4277
|
-
</View>
|
|
4278
|
-
<Text style={styles.analyticsTopEventName} numberOfLines={2}>
|
|
4279
|
-
{name}
|
|
4289
|
+
</ScrollView>) : activeTab === 'analytics' ? (<View style={{ flex: 1 }}>
|
|
4290
|
+
{selectedEvent != null ? (<AnalyticsDetail event={selectedEvent}/>) : analyticsSubTab === 'top_events' ? (<FlatList data={topEventsArray} keyExtractor={item => item[0]} contentContainerStyle={[
|
|
4291
|
+
styles.listContent,
|
|
4292
|
+
{ paddingHorizontal: 16, paddingTop: 12 },
|
|
4293
|
+
]} renderItem={({ item: [name, count], index }) => {
|
|
4294
|
+
const maxCount = topEventsArray[0]?.[1] || 1;
|
|
4295
|
+
const pct = Math.max(6, (count / maxCount) * 100);
|
|
4296
|
+
const color = getEventColor(name);
|
|
4297
|
+
return (<AnimatedEntrance index={index} distance={8} style={[
|
|
4298
|
+
styles.analyticsTopEventsCard,
|
|
4299
|
+
{ marginBottom: 6, paddingVertical: 10, paddingHorizontal: 12 },
|
|
4300
|
+
]}>
|
|
4301
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 10 }}>
|
|
4302
|
+
<Text style={{
|
|
4303
|
+
fontFamily: AppFonts.interBold,
|
|
4304
|
+
fontSize: 11,
|
|
4305
|
+
color: color,
|
|
4306
|
+
width: 18,
|
|
4307
|
+
textAlign: 'center',
|
|
4308
|
+
}}>
|
|
4309
|
+
{index + 1}
|
|
4280
4310
|
</Text>
|
|
4311
|
+
<View style={{ flex: 1, gap: 4 }}>
|
|
4312
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
|
|
4313
|
+
<Text style={{
|
|
4314
|
+
fontFamily: AppFonts.interMedium,
|
|
4315
|
+
fontSize: 12.5,
|
|
4316
|
+
color: AppColors.primaryBlack,
|
|
4317
|
+
flex: 1,
|
|
4318
|
+
}} numberOfLines={1}>
|
|
4319
|
+
{name}
|
|
4320
|
+
</Text>
|
|
4321
|
+
<Text style={{
|
|
4322
|
+
fontFamily: AppFonts.interBold,
|
|
4323
|
+
fontSize: 12,
|
|
4324
|
+
color: color,
|
|
4325
|
+
marginLeft: 8,
|
|
4326
|
+
}}>
|
|
4327
|
+
{count}
|
|
4328
|
+
</Text>
|
|
4329
|
+
</View>
|
|
4330
|
+
<View style={{ height: 3, backgroundColor: AppColors.grayBackground, borderRadius: 2, overflow: 'hidden' }}>
|
|
4331
|
+
<LinearGradient colors={[color, `${color}88`]} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={{
|
|
4332
|
+
height: '100%',
|
|
4333
|
+
borderRadius: 2,
|
|
4334
|
+
width: `${pct}%`,
|
|
4335
|
+
}}/>
|
|
4336
|
+
</View>
|
|
4337
|
+
</View>
|
|
4281
4338
|
</View>
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
width: `${Math.max(6, (count / maxCount) * 100)}%`,
|
|
4287
|
-
},
|
|
4288
|
-
]}/>
|
|
4289
|
-
</View>
|
|
4290
|
-
<Text style={styles.analyticsTopEventCount}>
|
|
4291
|
-
{count}
|
|
4292
|
-
</Text>
|
|
4339
|
+
</AnimatedEntrance>);
|
|
4340
|
+
}} ListEmptyComponent={<View style={styles.emptyContainer}>
|
|
4341
|
+
<View style={styles.emptyIconWrap}>
|
|
4342
|
+
<EmptyRadarIcon color={AppColors.purple} size={32}/>
|
|
4293
4343
|
</View>
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
item.
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
if (routeInfo &&
|
|
4327
|
-
routeInfo.path !== 'Navigators') {
|
|
4328
|
-
const parts = routeInfo.path.split(' ➔ ');
|
|
4329
|
-
screenName = parts[parts.length - 1];
|
|
4344
|
+
<Text style={styles.emptyTitle}>No Top Events</Text>
|
|
4345
|
+
</View>}/>) : (<FlatList data={filteredAnalyticsEvents} keyExtractor={item => item.id.toString()} renderItem={({ item, index }) => {
|
|
4346
|
+
const prev = filteredAnalyticsEvents[index + 1];
|
|
4347
|
+
const next = filteredAnalyticsEvents[index - 1];
|
|
4348
|
+
const msSincePrev = prev
|
|
4349
|
+
? item.timestamp - prev.timestamp
|
|
4350
|
+
: undefined;
|
|
4351
|
+
const thisMin = Math.floor(item.timestamp / 60000);
|
|
4352
|
+
const nextMin = next
|
|
4353
|
+
? Math.floor(next.timestamp / 60000)
|
|
4354
|
+
: -1;
|
|
4355
|
+
const showTimestamp = index === 0 || thisMin !== nextMin;
|
|
4356
|
+
return (<AnimatedEntrance index={index} distance={8}>
|
|
4357
|
+
<AnalyticsEventCard event={item} onPress={() => {
|
|
4358
|
+
animateNextLayout();
|
|
4359
|
+
setSelectedEvent(item);
|
|
4360
|
+
}} isNew={newEventIds.has(item.id)} searchStr={analyticsSearch} isFirst={index === 0} isLast={index === filteredAnalyticsEvents.length - 1} msSincePrev={msSincePrev} showTimestamp={showTimestamp} computedScreenName={(() => {
|
|
4361
|
+
let screenName = item.screenName ||
|
|
4362
|
+
item.screenClass ||
|
|
4363
|
+
item.pageTitle ||
|
|
4364
|
+
item.pageLocation ||
|
|
4365
|
+
item.params?.firebase_screen ||
|
|
4366
|
+
item.params?.screen_name ||
|
|
4367
|
+
item.params?.firebase_screen_class ||
|
|
4368
|
+
item.params?.screen_class;
|
|
4369
|
+
const routeInfo = logRouteMapRef.current.get(item.id + 1000000);
|
|
4370
|
+
if (!screenName) {
|
|
4371
|
+
if (routeInfo &&
|
|
4372
|
+
routeInfo.path !== 'Navigators') {
|
|
4373
|
+
const parts = routeInfo.path.split(' ➔ ');
|
|
4374
|
+
screenName = parts[parts.length - 1];
|
|
4375
|
+
}
|
|
4330
4376
|
}
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
</
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
}
|
|
4354
|
-
|
|
4377
|
+
return screenName;
|
|
4378
|
+
})()}/>
|
|
4379
|
+
</AnimatedEntrance>);
|
|
4380
|
+
}} initialNumToRender={20} maxToRenderPerBatch={20} windowSize={5} removeClippedSubviews={false} ListEmptyComponent={<View style={styles.emptyContainer}>
|
|
4381
|
+
<View style={styles.emptyIconWrap}>
|
|
4382
|
+
<EmptyRadarIcon color={AppColors.purple} size={32}/>
|
|
4383
|
+
</View>
|
|
4384
|
+
<Text style={styles.emptyTitle}>
|
|
4385
|
+
{analyticsSearch.length > 0
|
|
4386
|
+
? 'No matching events'
|
|
4387
|
+
: 'No analytics events yet'}
|
|
4388
|
+
</Text>
|
|
4389
|
+
<Text style={styles.emptySub}>
|
|
4390
|
+
{analyticsSearch.length > 0
|
|
4391
|
+
? 'Try adjusting your search.'
|
|
4392
|
+
: 'Call setupAnalyticsLogger(analytics()) at app start.'}
|
|
4393
|
+
</Text>
|
|
4394
|
+
</View>} contentContainerStyle={[
|
|
4395
|
+
styles.listContent,
|
|
4396
|
+
filteredAnalyticsEvents.length === 0 && {
|
|
4397
|
+
flexGrow: 1,
|
|
4398
|
+
},
|
|
4399
|
+
]} keyboardShouldPersistTaps="handled"/>)}
|
|
4400
|
+
</View>) : activeTab === 'apis' && selected == null ? (<View style={{ flex: 1 }}>
|
|
4355
4401
|
<FlatList ref={apisListRef} data={groupedData} keyExtractor={item => item?.id?.toString()} renderItem={renderItem} initialNumToRender={10} maxToRenderPerBatch={10} windowSize={5} removeClippedSubviews={true} ListHeaderComponent={<View style={{ marginTop: 8 }}>
|
|
4356
4402
|
<View style={styles.toolbarRow}>
|
|
4357
4403
|
<View style={styles.searchContainer}>
|