react-native-inapp-inspector 1.1.26 → 1.1.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +1 -0
- package/android/src/main/java/com/inappinspector/NetworkInspectorModule.java +34 -0
- package/dist/commonjs/components/ErrorBoundary.d.ts +1 -1
- package/dist/commonjs/components/ErrorBoundary.js +530 -100
- package/dist/commonjs/components/Inspector/AnalyticsTab.js +176 -126
- package/dist/commonjs/components/Inspector/BundleTab.d.ts +1 -0
- package/dist/commonjs/components/Inspector/BundleTab.js +145 -21
- package/dist/commonjs/components/Inspector/CrashTab.js +0 -8
- package/dist/commonjs/components/Inspector/NetworkDetail.js +41 -0
- package/dist/commonjs/components/Inspector/PerformanceTab.d.ts +5 -0
- package/dist/commonjs/components/Inspector/PerformanceTab.js +588 -155
- package/dist/commonjs/components/Inspector/SettingsPanel.js +57 -22
- package/dist/commonjs/components/Inspector/TabBar.js +13 -1
- package/dist/commonjs/components/LogCard.js +75 -34
- package/dist/commonjs/components/NetworkIcons.d.ts +112 -102
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/analyticsLogger.d.ts +1 -11
- package/dist/commonjs/customHooks/analyticsLogger.js +8 -1
- package/dist/commonjs/customHooks/bundleAnalyzer.js +121 -124
- package/dist/commonjs/customHooks/networkLogger.d.ts +1 -0
- package/dist/commonjs/customHooks/networkLogger.js +16 -0
- package/dist/commonjs/customHooks/performanceTracker.d.ts +74 -0
- package/dist/commonjs/customHooks/performanceTracker.js +546 -392
- package/dist/commonjs/customHooks/reduxLogger.d.ts +1 -0
- package/dist/commonjs/customHooks/reduxLogger.js +3 -1
- package/dist/commonjs/helpers/index.js +27 -3
- package/dist/commonjs/i18n/locales/en.json +225 -4
- package/dist/commonjs/index.d.ts +1 -1
- package/dist/commonjs/index.js +36 -2
- package/dist/commonjs/styles/index.d.ts +3 -1
- package/dist/commonjs/styles/index.js +8 -6
- package/dist/commonjs/types/interfaces.d.ts +3 -0
- package/dist/esm/components/ErrorBoundary.d.ts +1 -1
- package/dist/esm/components/ErrorBoundary.js +498 -101
- package/dist/esm/components/Inspector/AnalyticsTab.js +177 -127
- package/dist/esm/components/Inspector/BundleTab.d.ts +1 -0
- package/dist/esm/components/Inspector/BundleTab.js +145 -23
- package/dist/esm/components/Inspector/CrashTab.js +0 -8
- package/dist/esm/components/Inspector/NetworkDetail.js +41 -0
- package/dist/esm/components/Inspector/PerformanceTab.d.ts +5 -0
- package/dist/esm/components/Inspector/PerformanceTab.js +591 -158
- package/dist/esm/components/Inspector/SettingsPanel.js +57 -22
- package/dist/esm/components/Inspector/TabBar.js +13 -1
- package/dist/esm/components/LogCard.js +75 -34
- package/dist/esm/components/NetworkIcons.d.ts +112 -102
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/analyticsLogger.d.ts +1 -11
- package/dist/esm/customHooks/analyticsLogger.js +6 -0
- package/dist/esm/customHooks/bundleAnalyzer.js +121 -124
- package/dist/esm/customHooks/networkLogger.d.ts +1 -0
- package/dist/esm/customHooks/networkLogger.js +16 -0
- package/dist/esm/customHooks/performanceTracker.d.ts +74 -0
- package/dist/esm/customHooks/performanceTracker.js +531 -391
- package/dist/esm/customHooks/reduxLogger.d.ts +1 -0
- package/dist/esm/customHooks/reduxLogger.js +1 -0
- package/dist/esm/helpers/index.js +27 -3
- package/dist/esm/i18n/locales/en.json +225 -4
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +24 -3
- package/dist/esm/styles/index.d.ts +3 -1
- package/dist/esm/styles/index.js +8 -6
- package/dist/esm/types/interfaces.d.ts +3 -0
- package/ios/NetworkInspectorModule.h +2 -0
- package/ios/NetworkInspectorModule.m +10 -0
- package/package.json +1 -1
|
@@ -8,11 +8,14 @@ import EndOfListFooter from '../EndOfListFooter';
|
|
|
8
8
|
import styles from '../../styles';
|
|
9
9
|
import { AppColors } from '../../styles/AppColors';
|
|
10
10
|
import { AppFonts } from '../../styles/AppFonts';
|
|
11
|
+
import { useTranslation } from '../../i18n';
|
|
12
|
+
import Svg, { Path, Line, Circle, G, Defs, LinearGradient as SvgLinearGradient, Stop, } from 'react-native-svg';
|
|
11
13
|
import TouchableScale from '../TouchableScale';
|
|
12
14
|
import { getCurrentUserId, getCurrentUserProperties, getDefaultEventParameters, getCollectionEnabled, } from '../../customHooks/analyticsLogger';
|
|
13
15
|
import { getEventCategory, } from '../../helpers';
|
|
14
|
-
import { SearchIcon, ClearIcon, TrashIcon, EmptyRadarIcon, HeaderPauseIcon, FilterIcon, CartIcon, GlobeIcon, BoltIcon, SparkleIcon,
|
|
16
|
+
import { SearchIcon, ClearIcon, TrashIcon, EmptyRadarIcon, HeaderPauseIcon, FilterIcon, CartIcon, GlobeIcon, BoltIcon, SparkleIcon, PinIcon, MoneyIcon, } from '../NetworkIcons';
|
|
15
17
|
const AnalyticsHeader = React.memo(() => {
|
|
18
|
+
const { t } = useTranslation();
|
|
16
19
|
const { analyticsEvents, filteredAnalyticsEvents, analyticsFilters, setAnalyticsFilters, analyticsHeaderExpanded, setAnalyticsHeaderExpanded, } = useInspector();
|
|
17
20
|
const userId = getCurrentUserId();
|
|
18
21
|
const userProperties = getCurrentUserProperties();
|
|
@@ -97,20 +100,31 @@ const AnalyticsHeader = React.memo(() => {
|
|
|
97
100
|
}
|
|
98
101
|
});
|
|
99
102
|
};
|
|
100
|
-
// 12-Bucket GA4 Realtime Stacked Histogram Graph (-30m / 30s to NOW)
|
|
103
|
+
// 12-Bucket GA4 Realtime Stacked Histogram & Spline Wave Graph (-30m / 30s to NOW)
|
|
101
104
|
const BUCKET_COUNT = 12;
|
|
102
|
-
const chartHeight =
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
system: 0,
|
|
108
|
-
custom: 0,
|
|
109
|
-
total: 0,
|
|
110
|
-
}));
|
|
105
|
+
const chartHeight = 64;
|
|
106
|
+
const svgWidth = 320;
|
|
107
|
+
const [selectedBucketIdx, setSelectedBucketIdx] = useState(null);
|
|
108
|
+
const histogramData = useMemo(() => {
|
|
109
|
+
const buckets = [];
|
|
111
110
|
const now = Date.now();
|
|
112
111
|
const windowMs = 60000; // 60s window
|
|
113
112
|
const bucketDuration = windowMs / BUCKET_COUNT;
|
|
113
|
+
for (let i = 0; i < BUCKET_COUNT; i++) {
|
|
114
|
+
const bucketAgeSec = Math.round(((BUCKET_COUNT - 1 - i) * bucketDuration) / 1000);
|
|
115
|
+
buckets.push({
|
|
116
|
+
index: i,
|
|
117
|
+
ecommerce: 0,
|
|
118
|
+
page_view: 0,
|
|
119
|
+
system: 0,
|
|
120
|
+
custom: 0,
|
|
121
|
+
total: 0,
|
|
122
|
+
x: (i / (BUCKET_COUNT - 1)) * (svgWidth - 24) + 12,
|
|
123
|
+
y: chartHeight - 12,
|
|
124
|
+
isLatest: i === BUCKET_COUNT - 1,
|
|
125
|
+
ageLabel: i === BUCKET_COUNT - 1 ? t('analytics.timeNow') : `-${bucketAgeSec}s`,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
114
128
|
for (const e of filteredAnalyticsEvents) {
|
|
115
129
|
const age = now - e.timestamp;
|
|
116
130
|
if (age >= 0 && age < windowMs) {
|
|
@@ -131,30 +145,43 @@ const AnalyticsHeader = React.memo(() => {
|
|
|
131
145
|
}
|
|
132
146
|
}
|
|
133
147
|
const maxVal = Math.max(...buckets.map(b => b.total), 4);
|
|
134
|
-
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
const screenH = b.total > 0 ? (b.page_view / b.total) * totalH : 0;
|
|
138
|
-
const sysH = b.total > 0 ? (b.system / b.total) * totalH : 0;
|
|
139
|
-
const custH = b.total > 0 ? (b.custom / b.total) * totalH : totalH;
|
|
140
|
-
return {
|
|
141
|
-
index: idx,
|
|
142
|
-
total: b.total,
|
|
143
|
-
totalHeight: totalH,
|
|
144
|
-
ecomHeight: ecomH,
|
|
145
|
-
screenHeight: screenH,
|
|
146
|
-
sysHeight: sysH,
|
|
147
|
-
custHeight: custH,
|
|
148
|
-
isLatest: idx === BUCKET_COUNT - 1,
|
|
149
|
-
};
|
|
148
|
+
buckets.forEach(b => {
|
|
149
|
+
const normalizedH = (b.total / maxVal) * (chartHeight - 22);
|
|
150
|
+
b.y = chartHeight - 10 - normalizedH;
|
|
150
151
|
});
|
|
151
|
-
|
|
152
|
+
// Generate Cubic Bézier Spline paths
|
|
153
|
+
let linePath = `M ${buckets[0].x.toFixed(1)} ${buckets[0].y.toFixed(1)}`;
|
|
154
|
+
for (let i = 0; i < buckets.length - 1; i++) {
|
|
155
|
+
const p0 = buckets[Math.max(0, i - 1)];
|
|
156
|
+
const p1 = buckets[i];
|
|
157
|
+
const p2 = buckets[i + 1];
|
|
158
|
+
const p3 = buckets[Math.min(buckets.length - 1, i + 2)];
|
|
159
|
+
const cp1x = p1.x + (p2.x - p0.x) / 6;
|
|
160
|
+
const cp1y = p1.y + (p2.y - p0.y) / 6;
|
|
161
|
+
const cp2x = p2.x - (p3.x - p1.x) / 6;
|
|
162
|
+
const cp2y = p2.y - (p3.y - p1.y) / 6;
|
|
163
|
+
linePath += ` C ${cp1x.toFixed(1)} ${cp1y.toFixed(1)}, ${cp2x.toFixed(1)} ${cp2y.toFixed(1)}, ${p2.x.toFixed(1)} ${p2.y.toFixed(1)}`;
|
|
164
|
+
}
|
|
165
|
+
const lastB = buckets[buckets.length - 1];
|
|
166
|
+
const firstB = buckets[0];
|
|
167
|
+
const areaPath = `${linePath} L ${lastB.x.toFixed(1)} ${chartHeight - 4} L ${firstB.x.toFixed(1)} ${chartHeight - 4} Z`;
|
|
168
|
+
const peakVal = Math.max(...buckets.map(b => b.total), 0);
|
|
169
|
+
const eventRate = Math.round(buckets.reduce((a, b) => a + b.total, 0));
|
|
170
|
+
return {
|
|
171
|
+
buckets,
|
|
172
|
+
linePath,
|
|
173
|
+
areaPath,
|
|
174
|
+
peakVal,
|
|
175
|
+
eventRate,
|
|
176
|
+
};
|
|
177
|
+
}, [filteredAnalyticsEvents, chartHeight, svgWidth, t]);
|
|
178
|
+
const selectedBucket = selectedBucketIdx != null ? histogramData.buckets[selectedBucketIdx] : null;
|
|
152
179
|
return (<View style={styles.analyticsHeaderCard}>
|
|
153
180
|
{/* ── Top Header Row (GA4 Style) ─────────────────────────────────────── */}
|
|
154
181
|
<View style={styles.analyticsHeaderTop}>
|
|
155
182
|
<View style={{ flex: 1 }}>
|
|
156
183
|
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
157
|
-
<Text style={styles.analyticsHeaderTitle}>
|
|
184
|
+
<Text style={styles.analyticsHeaderTitle}>{t('analytics.realtimeStream')}</Text>
|
|
158
185
|
<View style={[
|
|
159
186
|
styles.statusDot,
|
|
160
187
|
{
|
|
@@ -172,11 +199,11 @@ const AnalyticsHeader = React.memo(() => {
|
|
|
172
199
|
fontFamily: AppFonts.interBold,
|
|
173
200
|
},
|
|
174
201
|
]}>
|
|
175
|
-
{isTrackingEnabled ? '
|
|
202
|
+
{isTrackingEnabled ? t('performance.live') : t('common.pause')}
|
|
176
203
|
</Text>
|
|
177
204
|
</View>
|
|
178
205
|
<Text style={styles.analyticsHeaderSubtitle} numberOfLines={1}>
|
|
179
|
-
{userId ?
|
|
206
|
+
{userId ? `${t('analytics.userId')}: ${userId}` : t('analytics.emptySubtitle')}
|
|
180
207
|
</Text>
|
|
181
208
|
</View>
|
|
182
209
|
|
|
@@ -185,7 +212,7 @@ const AnalyticsHeader = React.memo(() => {
|
|
|
185
212
|
setAnalyticsHeaderExpanded(!analyticsHeaderExpanded);
|
|
186
213
|
}}>
|
|
187
214
|
<Text style={styles.analyticsHeaderToggleText}>
|
|
188
|
-
{analyticsHeaderExpanded ? '
|
|
215
|
+
{analyticsHeaderExpanded ? t('common.close') : t('analytics.eventDetails')}
|
|
189
216
|
</Text>
|
|
190
217
|
</TouchableOpacity>
|
|
191
218
|
</View>
|
|
@@ -205,7 +232,7 @@ const AnalyticsHeader = React.memo(() => {
|
|
|
205
232
|
flexDirection: 'row',
|
|
206
233
|
justifyContent: 'space-between',
|
|
207
234
|
alignItems: 'flex-start',
|
|
208
|
-
marginBottom:
|
|
235
|
+
marginBottom: 6,
|
|
209
236
|
}}>
|
|
210
237
|
<View>
|
|
211
238
|
<View style={{ flexDirection: 'row', alignItems: 'baseline', gap: 6 }}>
|
|
@@ -222,13 +249,33 @@ const AnalyticsHeader = React.memo(() => {
|
|
|
222
249
|
fontSize: 10.5,
|
|
223
250
|
color: AppColors.grayTextWeak,
|
|
224
251
|
}}>
|
|
225
|
-
|
|
252
|
+
{t('analytics.eventsInWindow')}
|
|
226
253
|
</Text>
|
|
227
254
|
</View>
|
|
228
255
|
</View>
|
|
229
256
|
|
|
230
|
-
{/* Realtime Badges */}
|
|
257
|
+
{/* Realtime Rate Badges */}
|
|
231
258
|
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 5 }}>
|
|
259
|
+
<View style={{
|
|
260
|
+
flexDirection: 'row',
|
|
261
|
+
alignItems: 'center',
|
|
262
|
+
gap: 3,
|
|
263
|
+
backgroundColor: `${AppColors.purple}14`,
|
|
264
|
+
paddingHorizontal: 6,
|
|
265
|
+
paddingVertical: 2.5,
|
|
266
|
+
borderRadius: 4,
|
|
267
|
+
borderWidth: 1,
|
|
268
|
+
borderColor: `${AppColors.purple}2E`,
|
|
269
|
+
}}>
|
|
270
|
+
<Text style={{
|
|
271
|
+
fontFamily: AppFonts.interBold,
|
|
272
|
+
fontSize: 9.5,
|
|
273
|
+
color: AppColors.purple,
|
|
274
|
+
}}>
|
|
275
|
+
{t('analytics.eventVelocity', { rate: histogramData.eventRate })}
|
|
276
|
+
</Text>
|
|
277
|
+
</View>
|
|
278
|
+
|
|
232
279
|
{categoryStats.totalRevenue > 0 && (<View style={{
|
|
233
280
|
flexDirection: 'row',
|
|
234
281
|
alignItems: 'center',
|
|
@@ -249,127 +296,129 @@ const AnalyticsHeader = React.memo(() => {
|
|
|
249
296
|
${categoryStats.totalRevenue.toFixed(2)}
|
|
250
297
|
</Text>
|
|
251
298
|
</View>)}
|
|
252
|
-
<View style={{
|
|
253
|
-
flexDirection: 'row',
|
|
254
|
-
alignItems: 'center',
|
|
255
|
-
gap: 4,
|
|
256
|
-
backgroundColor: `${AppColors.brandPurple}14`,
|
|
257
|
-
paddingHorizontal: 6,
|
|
258
|
-
paddingVertical: 2.5,
|
|
259
|
-
borderRadius: 4,
|
|
260
|
-
borderWidth: 1,
|
|
261
|
-
borderColor: `${AppColors.brandPurple}2E`,
|
|
262
|
-
}}>
|
|
263
|
-
<TargetGoalIcon color={AppColors.brandPurple} size={10}/>
|
|
264
|
-
<Text style={{
|
|
265
|
-
fontFamily: AppFonts.interBold,
|
|
266
|
-
fontSize: 9.5,
|
|
267
|
-
color: AppColors.brandPurple,
|
|
268
|
-
}}>
|
|
269
|
-
Live Telemetry
|
|
270
|
-
</Text>
|
|
271
|
-
</View>
|
|
272
299
|
</View>
|
|
273
300
|
</View>
|
|
274
301
|
|
|
275
|
-
{/*
|
|
276
|
-
<View style={{
|
|
277
|
-
|
|
302
|
+
{/* ── High Precision SVG Spline Area Graph ── */}
|
|
303
|
+
<View style={{ height: chartHeight, position: 'relative' }}>
|
|
304
|
+
<Svg width="100%" height={chartHeight} viewBox={`0 0 ${svgWidth} ${chartHeight}`}>
|
|
305
|
+
<Defs>
|
|
306
|
+
<SvgLinearGradient id="telemetryAreaGrad" x1="0" y1="0" x2="0" y2="1">
|
|
307
|
+
<Stop offset="0%" stopColor={AppColors.brandPurple} stopOpacity="0.4"/>
|
|
308
|
+
<Stop offset="80%" stopColor={AppColors.brandPurple} stopOpacity="0.05"/>
|
|
309
|
+
<Stop offset="100%" stopColor={AppColors.brandPurple} stopOpacity="0.0"/>
|
|
310
|
+
</SvgLinearGradient>
|
|
311
|
+
</Defs>
|
|
312
|
+
|
|
313
|
+
{/* Baseline & Grid lines */}
|
|
314
|
+
<Line x1="8" y1={chartHeight - 6} x2={svgWidth - 8} y2={chartHeight - 6} stroke={AppColors.dividerColor} strokeWidth="1"/>
|
|
315
|
+
<Line x1="8" y1={chartHeight / 2} x2={svgWidth - 8} y2={chartHeight / 2} stroke={AppColors.dividerColor} strokeWidth="0.8" strokeDasharray="3,3"/>
|
|
316
|
+
|
|
317
|
+
{/* Glowing Area Fill */}
|
|
318
|
+
<Path d={histogramData.areaPath} fill="url(#telemetryAreaGrad)"/>
|
|
319
|
+
|
|
320
|
+
{/* Smooth Spline Wave Stroke */}
|
|
321
|
+
<Path d={histogramData.linePath} fill="none" stroke={AppColors.brandPurple} strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"/>
|
|
322
|
+
|
|
323
|
+
{/* Data Points & Active Bucket Indicators */}
|
|
324
|
+
{histogramData.buckets.map((b, idx) => {
|
|
325
|
+
const isSelected = selectedBucketIdx === idx;
|
|
326
|
+
return (<G key={b.index}>
|
|
327
|
+
{isSelected && (<Line x1={b.x} y1={4} x2={b.x} y2={chartHeight - 6} stroke={AppColors.brandPurple} strokeWidth="1.2" strokeDasharray="2,2"/>)}
|
|
328
|
+
|
|
329
|
+
{b.total > 0 && (<Circle cx={b.x} cy={b.y} r={isSelected ? 4.5 : 2.8} fill={isSelected ? AppColors.brandPurple : AppColors.white} stroke={AppColors.brandPurple} strokeWidth={isSelected ? 2 : 1.5}/>)}
|
|
330
|
+
|
|
331
|
+
{b.isLatest && (<G>
|
|
332
|
+
<Circle cx={b.x} cy={b.y} r="6.5" fill={AppColors.brandPurple} opacity="0.22"/>
|
|
333
|
+
<Circle cx={b.x} cy={b.y} r="3" fill={AppColors.brandPurple}/>
|
|
334
|
+
</G>)}
|
|
335
|
+
</G>);
|
|
336
|
+
})}
|
|
337
|
+
</Svg>
|
|
338
|
+
|
|
339
|
+
{/* Invisible Touch Columns for Interactive Bucket Selection */}
|
|
340
|
+
<View style={{
|
|
341
|
+
position: 'absolute',
|
|
342
|
+
top: 0,
|
|
343
|
+
left: 0,
|
|
344
|
+
right: 0,
|
|
345
|
+
bottom: 0,
|
|
278
346
|
flexDirection: 'row',
|
|
279
|
-
alignItems: 'flex-end',
|
|
280
|
-
justifyContent: 'space-between',
|
|
281
|
-
paddingHorizontal: 2,
|
|
282
|
-
paddingBottom: 2,
|
|
283
|
-
borderBottomWidth: 1,
|
|
284
|
-
borderBottomColor: AppColors.dividerColor,
|
|
285
347
|
}}>
|
|
286
|
-
|
|
287
|
-
|
|
348
|
+
{histogramData.buckets.map((b, idx) => (<TouchableOpacity key={b.index} style={{ flex: 1, height: '100%' }} activeOpacity={0.8} onPress={() => setSelectedBucketIdx(selectedBucketIdx === idx ? null : idx)}/>))}
|
|
349
|
+
</View>
|
|
350
|
+
</View>
|
|
351
|
+
|
|
352
|
+
{/* Selected Bucket Quick Breakdown Overlay */}
|
|
353
|
+
{selectedBucket && (<View style={{
|
|
354
|
+
flexDirection: 'row',
|
|
288
355
|
alignItems: 'center',
|
|
289
|
-
justifyContent: '
|
|
290
|
-
|
|
291
|
-
|
|
356
|
+
justifyContent: 'space-between',
|
|
357
|
+
backgroundColor: AppColors.white,
|
|
358
|
+
borderRadius: 6,
|
|
359
|
+
paddingHorizontal: 8,
|
|
360
|
+
paddingVertical: 4,
|
|
361
|
+
marginTop: 4,
|
|
362
|
+
borderWidth: 1,
|
|
363
|
+
borderColor: AppColors.brandPurple,
|
|
292
364
|
}}>
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
? AppColors.brandPurple
|
|
298
|
-
: AppColors.grayTextWeak,
|
|
299
|
-
marginBottom: 2,
|
|
300
|
-
}}>
|
|
301
|
-
{bar.total}
|
|
302
|
-
</Text>)}
|
|
303
|
-
{/* Stacked Category Segments Column */}
|
|
304
|
-
<View style={{
|
|
305
|
-
width: '100%',
|
|
306
|
-
maxWidth: 15,
|
|
307
|
-
height: bar.totalHeight,
|
|
308
|
-
borderRadius: 3,
|
|
309
|
-
overflow: 'hidden',
|
|
310
|
-
backgroundColor: bar.total > 0
|
|
311
|
-
? `${AppColors.grayBorderSecondary}40`
|
|
312
|
-
: `${AppColors.grayBorderSecondary}40`,
|
|
365
|
+
<Text style={{
|
|
366
|
+
fontFamily: AppFonts.interBold,
|
|
367
|
+
fontSize: 10,
|
|
368
|
+
color: AppColors.primaryBlack,
|
|
313
369
|
}}>
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
</>) : (<View style={{
|
|
332
|
-
height: 2.5,
|
|
333
|
-
backgroundColor: `${AppColors.grayBorderSecondary}80`,
|
|
334
|
-
}}/>)}
|
|
335
|
-
</View>
|
|
336
|
-
</View>))}
|
|
337
|
-
</View>
|
|
370
|
+
{t('analytics.selectedBucket', {
|
|
371
|
+
time: selectedBucket.ageLabel,
|
|
372
|
+
count: selectedBucket.total,
|
|
373
|
+
})}
|
|
374
|
+
</Text>
|
|
375
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
376
|
+
{selectedBucket.ecommerce > 0 && (<Text style={{ fontSize: 9, fontFamily: AppFonts.interBold, color: AppColors.amber700 }}>
|
|
377
|
+
Ecom: {selectedBucket.ecommerce}
|
|
378
|
+
</Text>)}
|
|
379
|
+
{selectedBucket.page_view > 0 && (<Text style={{ fontSize: 9, fontFamily: AppFonts.interBold, color: AppColors.sky500 }}>
|
|
380
|
+
Screen: {selectedBucket.page_view}
|
|
381
|
+
</Text>)}
|
|
382
|
+
{selectedBucket.custom > 0 && (<Text style={{ fontSize: 9, fontFamily: AppFonts.interBold, color: AppColors.brandPurple }}>
|
|
383
|
+
Custom: {selectedBucket.custom}
|
|
384
|
+
</Text>)}
|
|
385
|
+
</View>
|
|
386
|
+
</View>)}
|
|
338
387
|
|
|
339
388
|
{/* Timeline Axis Labels */}
|
|
340
389
|
<View style={{
|
|
341
390
|
flexDirection: 'row',
|
|
342
391
|
justifyContent: 'space-between',
|
|
343
392
|
marginTop: 4,
|
|
344
|
-
paddingHorizontal:
|
|
393
|
+
paddingHorizontal: 4,
|
|
345
394
|
}}>
|
|
346
395
|
<Text style={{
|
|
347
396
|
fontFamily: AppFonts.interMedium,
|
|
348
|
-
fontSize: 8,
|
|
397
|
+
fontSize: 8.5,
|
|
349
398
|
color: AppColors.grayTextWeak,
|
|
350
399
|
}}>
|
|
351
|
-
|
|
400
|
+
{t('analytics.time30mAgo')}
|
|
352
401
|
</Text>
|
|
353
402
|
<Text style={{
|
|
354
403
|
fontFamily: AppFonts.interMedium,
|
|
355
|
-
fontSize: 8,
|
|
404
|
+
fontSize: 8.5,
|
|
356
405
|
color: AppColors.grayTextWeak,
|
|
357
406
|
}}>
|
|
358
|
-
|
|
407
|
+
{t('analytics.time20mAgo')}
|
|
359
408
|
</Text>
|
|
360
409
|
<Text style={{
|
|
361
410
|
fontFamily: AppFonts.interMedium,
|
|
362
|
-
fontSize: 8,
|
|
411
|
+
fontSize: 8.5,
|
|
363
412
|
color: AppColors.grayTextWeak,
|
|
364
413
|
}}>
|
|
365
|
-
|
|
414
|
+
{t('analytics.time10mAgo')}
|
|
366
415
|
</Text>
|
|
367
416
|
<Text style={{
|
|
368
417
|
fontFamily: AppFonts.interBold,
|
|
369
|
-
fontSize: 8,
|
|
418
|
+
fontSize: 8.5,
|
|
370
419
|
color: AppColors.brandPurple,
|
|
371
420
|
}}>
|
|
372
|
-
|
|
421
|
+
{t('analytics.timeNow')}
|
|
373
422
|
</Text>
|
|
374
423
|
</View>
|
|
375
424
|
</View>
|
|
@@ -648,26 +697,26 @@ const AnalyticsHeader = React.memo(() => {
|
|
|
648
697
|
<View style={styles.analyticsStatsRow}>
|
|
649
698
|
<View style={styles.analyticsStatBox}>
|
|
650
699
|
<Text style={styles.analyticsStatValue}>{totalEvents}</Text>
|
|
651
|
-
<Text style={styles.analyticsStatLabel}>
|
|
700
|
+
<Text style={styles.analyticsStatLabel}>{t('analytics.eventCount', { count: totalEvents })}</Text>
|
|
652
701
|
</View>
|
|
653
702
|
<View style={styles.analyticsStatBox}>
|
|
654
703
|
<Text style={styles.analyticsStatValue}>
|
|
655
704
|
{Object.keys(userProperties).length}
|
|
656
705
|
</Text>
|
|
657
|
-
<Text style={styles.analyticsStatLabel}>
|
|
706
|
+
<Text style={styles.analyticsStatLabel}>{t('analytics.props')}</Text>
|
|
658
707
|
</View>
|
|
659
708
|
<View style={styles.analyticsStatBox}>
|
|
660
709
|
<Text style={styles.analyticsStatValue}>
|
|
661
710
|
{Object.keys(defaultParams).length}
|
|
662
711
|
</Text>
|
|
663
|
-
<Text style={styles.analyticsStatLabel}>
|
|
712
|
+
<Text style={styles.analyticsStatLabel}>{t('analytics.defaultParameters')}</Text>
|
|
664
713
|
</View>
|
|
665
714
|
</View>
|
|
666
715
|
|
|
667
716
|
{/* Details Section */}
|
|
668
717
|
{(hasUserProps || hasDefaultParams) && (<View style={styles.analyticsHeaderDetails}>
|
|
669
718
|
{hasUserProps && (<View style={{ marginBottom: 10 }}>
|
|
670
|
-
<Text style={styles.detailsGroupTitle}>
|
|
719
|
+
<Text style={styles.detailsGroupTitle}>{t('analytics.userProperties')}</Text>
|
|
671
720
|
{Object.entries(userProperties).map(([k, v]) => (<View key={k} style={styles.detailsRow}>
|
|
672
721
|
<Text style={styles.detailsKey} selectable={true}>{k}</Text>
|
|
673
722
|
<Text style={styles.detailsValue} selectable={true}>{String(v)}</Text>
|
|
@@ -675,7 +724,7 @@ const AnalyticsHeader = React.memo(() => {
|
|
|
675
724
|
</View>)}
|
|
676
725
|
|
|
677
726
|
{hasDefaultParams && (<View>
|
|
678
|
-
<Text style={styles.detailsGroupTitle}>
|
|
727
|
+
<Text style={styles.detailsGroupTitle}>{t('analytics.defaultParameters')}</Text>
|
|
679
728
|
{Object.entries(defaultParams).map(([k, v]) => (<View key={k} style={styles.detailsRow}>
|
|
680
729
|
<Text style={styles.detailsKey} selectable={true}>{k}</Text>
|
|
681
730
|
<Text style={styles.detailsValue} selectable={true}>{String(v)}</Text>
|
|
@@ -686,6 +735,7 @@ const AnalyticsHeader = React.memo(() => {
|
|
|
686
735
|
</View>);
|
|
687
736
|
});
|
|
688
737
|
const AnalyticsTab = React.memo(() => {
|
|
738
|
+
const { t } = useTranslation();
|
|
689
739
|
const { filteredAnalyticsEvents, analyticsSearch, setAnalyticsSearch, handleDelete, selectedEvent, setSelectedEvent, newEventIds, logRouteMapRef, isAnalyticsLayoutReady, setIsAnalyticsLayoutReady, isAnalyticsPaused, setIsAnalyticsPaused, isAnalyticsFilterApplied, } = useInspector();
|
|
690
740
|
const [isFilterModalOpen, setIsFilterModalOpen] = useState(false);
|
|
691
741
|
const keyExtractor = useCallback((item, index) => item?.id?.toString() ?? index.toString(), []);
|
|
@@ -43,5 +43,6 @@ export interface TreeNode {
|
|
|
43
43
|
fileCount: number;
|
|
44
44
|
children: TreeNode[];
|
|
45
45
|
}
|
|
46
|
+
export declare const downloadBundleFile: (file: BundleFileItem, scriptURL?: string) => Promise<void>;
|
|
46
47
|
declare const BundleTab: React.MemoExoticComponent<() => React.JSX.Element>;
|
|
47
48
|
export default BundleTab;
|