react-native-inapp-inspector 1.1.21 → 1.1.22
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 +5 -3
- package/dist/commonjs/components/AnalyticsEventCard.d.ts +0 -1
- package/dist/commonjs/components/AnalyticsEventCard.js +85 -96
- package/dist/commonjs/components/Inspector/BundleTab.js +486 -651
- package/dist/commonjs/components/Inspector/PerformanceTab.js +185 -244
- package/dist/commonjs/components/Inspector/ReduxDetail.js +2 -2
- package/dist/commonjs/components/Inspector/ReduxTab.js +3 -3
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/bundleAnalyzer.d.ts +115 -0
- package/dist/commonjs/customHooks/bundleAnalyzer.js +561 -0
- package/dist/commonjs/customHooks/performanceTracker.d.ts +84 -0
- package/dist/commonjs/customHooks/performanceTracker.js +541 -0
- package/dist/commonjs/helpers/index.d.ts +15 -0
- package/dist/commonjs/helpers/index.js +112 -1
- package/dist/commonjs/i18n/locales/en.json +225 -2
- package/dist/commonjs/styles/AppColors.d.ts +110 -0
- package/dist/commonjs/styles/AppColors.js +114 -0
- package/dist/esm/components/AnalyticsDetail.js +5 -3
- package/dist/esm/components/AnalyticsEventCard.d.ts +0 -1
- package/dist/esm/components/AnalyticsEventCard.js +85 -95
- package/dist/esm/components/Inspector/BundleTab.js +489 -654
- package/dist/esm/components/Inspector/PerformanceTab.js +185 -244
- package/dist/esm/components/Inspector/ReduxDetail.js +2 -2
- package/dist/esm/components/Inspector/ReduxTab.js +3 -3
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/bundleAnalyzer.d.ts +115 -0
- package/dist/esm/customHooks/bundleAnalyzer.js +554 -0
- package/dist/esm/customHooks/performanceTracker.d.ts +84 -0
- package/dist/esm/customHooks/performanceTracker.js +537 -0
- package/dist/esm/helpers/index.d.ts +15 -0
- package/dist/esm/helpers/index.js +107 -0
- package/dist/esm/i18n/locales/en.json +225 -2
- package/dist/esm/styles/AppColors.d.ts +110 -0
- package/dist/esm/styles/AppColors.js +114 -0
- package/package.json +1 -1
|
@@ -44,160 +44,11 @@ const HighlightText_1 = __importDefault(require("../HighlightText"));
|
|
|
44
44
|
const EndOfListFooter_1 = __importDefault(require("../EndOfListFooter"));
|
|
45
45
|
const AppColors_1 = require("../../styles/AppColors");
|
|
46
46
|
const AppFonts_1 = require("../../styles/AppFonts");
|
|
47
|
+
const i18n_1 = require("../../i18n");
|
|
48
|
+
const helpers_1 = require("../../helpers");
|
|
47
49
|
const NetworkIcons_1 = require("../NetworkIcons");
|
|
48
|
-
const INITIAL_PERFORMANCE_EVENTS = [
|
|
49
|
-
{
|
|
50
|
-
id: 'perf-1',
|
|
51
|
-
timestamp: Date.now() - 48000,
|
|
52
|
-
type: 'fps_drop',
|
|
53
|
-
category: 'navigation',
|
|
54
|
-
fps: 38,
|
|
55
|
-
durationMs: 26.3,
|
|
56
|
-
label: 'Main Thread Spike during Navigation',
|
|
57
|
-
detail: 'Screen transition to ProductDetailScreen triggered heavy layout reconciliation and simultaneous component mounts.',
|
|
58
|
-
source: 'src/navigation/RootNavigator.tsx',
|
|
59
|
-
breakdown: { jsTimeMs: 18.2, uiTimeMs: 8.1, bridgeLatencyMs: 1.2 },
|
|
60
|
-
heapDeltaKb: 640,
|
|
61
|
-
advice: 'Defer non-critical offscreen hooks with InteractionManager.runAfterInteractions to preserve 60 FPS.',
|
|
62
|
-
severity: 'warning',
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
id: 'perf-2',
|
|
66
|
-
timestamp: Date.now() - 41000,
|
|
67
|
-
type: 'slow_render',
|
|
68
|
-
category: 'render',
|
|
69
|
-
fps: 42,
|
|
70
|
-
durationMs: 23.8,
|
|
71
|
-
label: 'FlatList Virtualization Re-render Pass',
|
|
72
|
-
detail: 'FlatList rendered 25 items simultaneously on orientation change without memoized row component.',
|
|
73
|
-
source: 'src/components/Inspector/NetworkTab.tsx',
|
|
74
|
-
breakdown: { jsTimeMs: 16.4, uiTimeMs: 7.4 },
|
|
75
|
-
heapDeltaKb: 380,
|
|
76
|
-
advice: 'Implement getItemLayout and React.memo(LogCard) to skip redundant diffing passes.',
|
|
77
|
-
severity: 'warning',
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
id: 'perf-3',
|
|
81
|
-
timestamp: Date.now() - 35000,
|
|
82
|
-
type: 'transition',
|
|
83
|
-
category: 'navigation',
|
|
84
|
-
fps: 59,
|
|
85
|
-
durationMs: 16.9,
|
|
86
|
-
label: 'Native Modal Slide-Up Transition',
|
|
87
|
-
detail: 'Hardware accelerated native driver animated transform running smoothly at sustained 60 FPS.',
|
|
88
|
-
source: 'src/components/Inspector/MainScreen.tsx',
|
|
89
|
-
breakdown: { jsTimeMs: 2.1, uiTimeMs: 14.8 },
|
|
90
|
-
heapDeltaKb: 120,
|
|
91
|
-
advice: 'Using nativeDriver: true successfully prevents JS thread blocking during animations.',
|
|
92
|
-
severity: 'optimal',
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
id: 'perf-4',
|
|
96
|
-
timestamp: Date.now() - 28000,
|
|
97
|
-
type: 'memory',
|
|
98
|
-
category: 'memory',
|
|
99
|
-
fps: 60,
|
|
100
|
-
durationMs: 16.6,
|
|
101
|
-
label: 'Hermes Generational Garbage Collection',
|
|
102
|
-
detail: 'Minor generational GC cycle scavenged 4.2 MB ephemeral heap objects with sub-millisecond thread pause.',
|
|
103
|
-
source: 'Hermes VM Garbage Collector',
|
|
104
|
-
breakdown: { jsTimeMs: 3.1, uiTimeMs: 0.2 },
|
|
105
|
-
heapDeltaKb: -4280,
|
|
106
|
-
advice: 'Hermes generational garbage collector is operating within optimal sub-5ms limits.',
|
|
107
|
-
severity: 'optimal',
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
id: 'perf-5',
|
|
111
|
-
timestamp: Date.now() - 22000,
|
|
112
|
-
type: 'network',
|
|
113
|
-
category: 'io',
|
|
114
|
-
fps: 48,
|
|
115
|
-
durationMs: 20.8,
|
|
116
|
-
label: 'Large JSON Payload Deserialization',
|
|
117
|
-
detail: '50-item API response parse overhead in network adapter (185 KB JSON raw string).',
|
|
118
|
-
source: 'src/customHooks/networkLogger.ts',
|
|
119
|
-
breakdown: { jsTimeMs: 15.6, uiTimeMs: 5.2, bridgeLatencyMs: 2.1 },
|
|
120
|
-
heapDeltaKb: 890,
|
|
121
|
-
advice: 'Consider paginating API payloads or streaming responses if payload size exceeds 250 KB.',
|
|
122
|
-
severity: 'warning',
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
id: 'perf-6',
|
|
126
|
-
timestamp: Date.now() - 17000,
|
|
127
|
-
type: 'slow_render',
|
|
128
|
-
category: 'render',
|
|
129
|
-
fps: 52,
|
|
130
|
-
durationMs: 19.2,
|
|
131
|
-
label: 'Image Bitmap Decode & Rasterization',
|
|
132
|
-
detail: 'Retina raster decode for banner_dark.png (1200×630px raster buffer allocation).',
|
|
133
|
-
source: 'src/components/Inspector/BundleTab.tsx',
|
|
134
|
-
breakdown: { jsTimeMs: 3.4, uiTimeMs: 15.8 },
|
|
135
|
-
heapDeltaKb: 1450,
|
|
136
|
-
advice: 'Downscale asset dimensions or convert to WebP to reduce decode latency by ~65%.',
|
|
137
|
-
severity: 'warning',
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
id: 'perf-7',
|
|
141
|
-
timestamp: Date.now() - 12000,
|
|
142
|
-
type: 'bridge',
|
|
143
|
-
category: 'bridge',
|
|
144
|
-
fps: 60,
|
|
145
|
-
durationMs: 16.6,
|
|
146
|
-
label: 'Native TurboModule JSI Invocation',
|
|
147
|
-
detail: 'AsyncStorage / MMKV preferences transaction read across 32 configuration keys.',
|
|
148
|
-
source: 'src/helpers/settingsStore.ts',
|
|
149
|
-
breakdown: { jsTimeMs: 1.8, uiTimeMs: 0.8, bridgeLatencyMs: 0.4 },
|
|
150
|
-
heapDeltaKb: 45,
|
|
151
|
-
advice: 'Direct C++ JSI Turbomodule bindings completely bypass legacy JSON bridge serialization overhead.',
|
|
152
|
-
severity: 'optimal',
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
id: 'perf-8',
|
|
156
|
-
timestamp: Date.now() - 8000,
|
|
157
|
-
type: 'slow_render',
|
|
158
|
-
category: 'render',
|
|
159
|
-
fps: 60,
|
|
160
|
-
durationMs: 16.6,
|
|
161
|
-
label: 'Redux Action State Tree Diffing',
|
|
162
|
-
detail: 'Redux dispatch pass evaluated 6 reducer slices and emitted state notification in 4.8ms.',
|
|
163
|
-
source: 'src/components/Inspector/ReduxTab.tsx',
|
|
164
|
-
breakdown: { jsTimeMs: 4.8, uiTimeMs: 1.2 },
|
|
165
|
-
heapDeltaKb: 180,
|
|
166
|
-
advice: 'State tree immutability preserved. Memoized selectors prevented redundant component renders.',
|
|
167
|
-
severity: 'optimal',
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
id: 'perf-9',
|
|
171
|
-
timestamp: Date.now() - 4000,
|
|
172
|
-
type: 'touch',
|
|
173
|
-
category: 'render',
|
|
174
|
-
fps: 60,
|
|
175
|
-
durationMs: 16.6,
|
|
176
|
-
label: 'Touch-to-Render Event Latency',
|
|
177
|
-
detail: 'Gesture responder dispatched tap event to TabBar button with immediate 60 FPS response.',
|
|
178
|
-
source: 'src/components/Inspector/TabBar.tsx',
|
|
179
|
-
breakdown: { jsTimeMs: 4.2, uiTimeMs: 2.1 },
|
|
180
|
-
heapDeltaKb: 30,
|
|
181
|
-
advice: 'Touch responder latency is well within standard 16.67ms frame budget.',
|
|
182
|
-
severity: 'optimal',
|
|
183
|
-
},
|
|
184
|
-
{
|
|
185
|
-
id: 'perf-10',
|
|
186
|
-
timestamp: Date.now() - 1500,
|
|
187
|
-
type: 'transition',
|
|
188
|
-
category: 'render',
|
|
189
|
-
fps: 60,
|
|
190
|
-
durationMs: 16.6,
|
|
191
|
-
label: 'C++ Yoga Flexbox Layout Pass',
|
|
192
|
-
detail: 'Inspector UI multi-tab card layout recalculation and font metrics pass in C++ Yoga engine.',
|
|
193
|
-
source: 'Yoga Flexbox Layout Engine',
|
|
194
|
-
breakdown: { jsTimeMs: 2.8, uiTimeMs: 3.4 },
|
|
195
|
-
heapDeltaKb: 65,
|
|
196
|
-
advice: 'Flexbox layout constraints are cached and computed efficiently with zero reflow penalties.',
|
|
197
|
-
severity: 'optimal',
|
|
198
|
-
},
|
|
199
|
-
];
|
|
200
50
|
const PerformanceTab = react_1.default.memo(() => {
|
|
51
|
+
const { t } = (0, i18n_1.useTranslation)();
|
|
201
52
|
// ─── Real-Time FPS Tracking ────────────────────────────────────────────────
|
|
202
53
|
const [isRecording, setIsRecording] = (0, react_1.useState)(true);
|
|
203
54
|
const [currentFps, setCurrentFps] = (0, react_1.useState)(60);
|
|
@@ -222,7 +73,7 @@ const PerformanceTab = react_1.default.memo(() => {
|
|
|
222
73
|
60, 59, 60, 60, 58, 60, 59, 60, 60, 60, 57, 60, 59, 60, 60, 58, 60, 60, 59, 60,
|
|
223
74
|
]);
|
|
224
75
|
// Performance Log Events
|
|
225
|
-
const [events, setEvents] = (0, react_1.useState)(
|
|
76
|
+
const [events, setEvents] = (0, react_1.useState)([]);
|
|
226
77
|
const [filterCategory, setFilterCategory] = (0, react_1.useState)('ALL');
|
|
227
78
|
const [search, setSearch] = (0, react_1.useState)('');
|
|
228
79
|
// ─── Live Frame Measurement Loop (1-Second Batch Interval) ────────────────
|
|
@@ -267,21 +118,22 @@ const PerformanceTab = react_1.default.memo(() => {
|
|
|
267
118
|
});
|
|
268
119
|
// Trigger log if noticeable frame drop
|
|
269
120
|
if (measuredFps < 50) {
|
|
121
|
+
const durationStr = (1000 / measuredFps).toFixed(1);
|
|
270
122
|
const newEvent = {
|
|
271
123
|
id: `drop-${Date.now()}`,
|
|
272
124
|
timestamp: Date.now(),
|
|
273
125
|
type: 'fps_drop',
|
|
274
126
|
category: 'render',
|
|
275
127
|
fps: measuredFps,
|
|
276
|
-
durationMs: Number(
|
|
277
|
-
label:
|
|
278
|
-
detail:
|
|
279
|
-
source: '
|
|
128
|
+
durationMs: Number(durationStr),
|
|
129
|
+
label: t('performance.liveFpsDip', { fps: measuredFps }),
|
|
130
|
+
detail: t('performance.liveFpsDipDetail', { duration: durationStr }),
|
|
131
|
+
source: t('performance.uiRenderThread'),
|
|
280
132
|
breakdown: {
|
|
281
133
|
jsTimeMs: Number(((1000 / measuredFps) * 0.65).toFixed(1)),
|
|
282
134
|
uiTimeMs: Number(((1000 / measuredFps) * 0.35).toFixed(1)),
|
|
283
135
|
},
|
|
284
|
-
advice: '
|
|
136
|
+
advice: t('performance.liveFpsDipAdvice'),
|
|
285
137
|
severity: measuredFps < 30 ? 'critical' : 'warning',
|
|
286
138
|
};
|
|
287
139
|
setEvents(prev => [newEvent, ...prev.slice(0, 49)]);
|
|
@@ -323,12 +175,76 @@ const PerformanceTab = react_1.default.memo(() => {
|
|
|
323
175
|
}, [events, search, filterCategory]);
|
|
324
176
|
// Overall Performance Score
|
|
325
177
|
const performanceScore = (0, react_1.useMemo)(() => {
|
|
326
|
-
if (avgFps >= 58)
|
|
327
|
-
return {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
178
|
+
if (avgFps >= 58) {
|
|
179
|
+
return {
|
|
180
|
+
score: '98/100',
|
|
181
|
+
grade: t('performance.excellent'),
|
|
182
|
+
color: AppColors_1.AppColors.emerald600,
|
|
183
|
+
bg: AppColors_1.AppColors.greenBg,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
if (avgFps >= 50) {
|
|
187
|
+
return {
|
|
188
|
+
score: '84/100',
|
|
189
|
+
grade: t('performance.good'),
|
|
190
|
+
color: AppColors_1.AppColors.firebaseOrange,
|
|
191
|
+
bg: AppColors_1.AppColors.amberBg,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
score: '58/100',
|
|
196
|
+
grade: t('performance.needsOptimization'),
|
|
197
|
+
color: AppColors_1.AppColors.errorColor,
|
|
198
|
+
bg: AppColors_1.AppColors.errorCardBg,
|
|
199
|
+
};
|
|
200
|
+
}, [avgFps, t]);
|
|
201
|
+
// ─── Dynamic Runtime Environment & Engine Diagnostics ──────────────────────
|
|
202
|
+
const runtimeDiagnostics = (0, react_1.useMemo)(() => {
|
|
203
|
+
const raw = (0, helpers_1.getRuntimeDiagnostics)();
|
|
204
|
+
const engineNameMap = {
|
|
205
|
+
hermes: t('performance.hermesAot'),
|
|
206
|
+
v8: t('performance.v8Jit'),
|
|
207
|
+
jsc: t('performance.jscEngine'),
|
|
208
|
+
};
|
|
209
|
+
const engineSubMap = {
|
|
210
|
+
hermes: t('performance.bytecodeCompiled'),
|
|
211
|
+
v8: t('performance.jitEngine'),
|
|
212
|
+
jsc: t('performance.webkitEngine'),
|
|
213
|
+
};
|
|
214
|
+
const archNameMap = {
|
|
215
|
+
fabric: t('performance.fabricJsi'),
|
|
216
|
+
paper: t('performance.paperBridge'),
|
|
217
|
+
};
|
|
218
|
+
const archSubMap = {
|
|
219
|
+
fabric: t('performance.directCppBindings'),
|
|
220
|
+
paper: t('performance.asyncJsonBridge'),
|
|
221
|
+
};
|
|
222
|
+
return {
|
|
223
|
+
jsEngineName: engineNameMap[raw.engineType],
|
|
224
|
+
jsEngineSub: engineSubMap[raw.engineType],
|
|
225
|
+
uiArchName: archNameMap[raw.archType],
|
|
226
|
+
uiArchSub: archSubMap[raw.archType],
|
|
227
|
+
usedHeapMb: raw.usedHeapMb,
|
|
228
|
+
totalAllocMb: raw.totalAllocMb,
|
|
229
|
+
};
|
|
230
|
+
}, [t]);
|
|
231
|
+
// ─── Dynamic 16.67ms Frame Budget Utilization ─────────────────────────────
|
|
232
|
+
const frameBudgetStats = (0, react_1.useMemo)(() => {
|
|
233
|
+
const frameDuration = avgFps > 0 ? 1000 / avgFps : 16.67;
|
|
234
|
+
const jsTime = Number(Math.max(1.0, Math.min(frameDuration * 0.45, 2.0 + jsLagMs)).toFixed(1));
|
|
235
|
+
const layoutTime = Number(Math.max(1.0, frameDuration * 0.2).toFixed(1));
|
|
236
|
+
const renderTime = Number(Math.max(1.0, frameDuration * 0.25).toFixed(1));
|
|
237
|
+
const totalUsed = jsTime + layoutTime + renderTime;
|
|
238
|
+
const freeTime = Math.max(0, Number((16.67 - totalUsed).toFixed(1)));
|
|
239
|
+
const headroomPercent = Math.max(0, Math.min(100, Math.round((freeTime / 16.67) * 100)));
|
|
240
|
+
return {
|
|
241
|
+
jsTime,
|
|
242
|
+
layoutTime,
|
|
243
|
+
renderTime,
|
|
244
|
+
freeTime,
|
|
245
|
+
headroomPercent,
|
|
246
|
+
};
|
|
247
|
+
}, [avgFps, jsLagMs]);
|
|
332
248
|
const clearEvents = () => {
|
|
333
249
|
setEvents([]);
|
|
334
250
|
};
|
|
@@ -337,7 +253,7 @@ const PerformanceTab = react_1.default.memo(() => {
|
|
|
337
253
|
<react_native_1.View style={perfStyles.headerBar}>
|
|
338
254
|
<react_native_1.View style={perfStyles.searchBox}>
|
|
339
255
|
<NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={15}/>
|
|
340
|
-
<react_native_1.TextInput placeholder=
|
|
256
|
+
<react_native_1.TextInput placeholder={t('performance.searchPlaceholder')} placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={search} onChangeText={setSearch} style={perfStyles.searchInput} autoCapitalize="none" autoCorrect={false}/>
|
|
341
257
|
{search ? (<TouchableScale_1.default onPress={() => setSearch('')}>
|
|
342
258
|
<NetworkIcons_1.CircleXIcon color={AppColors_1.AppColors.grayTextWeak} size={16}/>
|
|
343
259
|
</TouchableScale_1.default>) : null}
|
|
@@ -350,13 +266,13 @@ const PerformanceTab = react_1.default.memo(() => {
|
|
|
350
266
|
]}>
|
|
351
267
|
<react_native_1.View style={[
|
|
352
268
|
perfStyles.recordDot,
|
|
353
|
-
{ backgroundColor: isRecording ?
|
|
269
|
+
{ backgroundColor: isRecording ? AppColors_1.AppColors.emerald500 : AppColors_1.AppColors.amber500 },
|
|
354
270
|
]}/>
|
|
355
271
|
<react_native_1.Text style={[
|
|
356
272
|
perfStyles.recordBtnText,
|
|
357
|
-
{ color: isRecording ?
|
|
273
|
+
{ color: isRecording ? AppColors_1.AppColors.emerald600 : AppColors_1.AppColors.amber700 },
|
|
358
274
|
]}>
|
|
359
|
-
{isRecording ? '
|
|
275
|
+
{isRecording ? t('performance.live') : t('redux.paused')}
|
|
360
276
|
</react_native_1.Text>
|
|
361
277
|
</TouchableScale_1.default>
|
|
362
278
|
|
|
@@ -368,10 +284,10 @@ const PerformanceTab = react_1.default.memo(() => {
|
|
|
368
284
|
jankyFrameCount,
|
|
369
285
|
jsLagMs,
|
|
370
286
|
platform: react_native_1.Platform.OS,
|
|
371
|
-
engine:
|
|
287
|
+
engine: runtimeDiagnostics.jsEngineName,
|
|
372
288
|
totalEvents: events.length,
|
|
373
289
|
events,
|
|
374
|
-
})} label=
|
|
290
|
+
})} label={t('common.copyJson')}/>
|
|
375
291
|
</react_native_1.View>
|
|
376
292
|
</react_native_1.View>
|
|
377
293
|
|
|
@@ -379,34 +295,34 @@ const PerformanceTab = react_1.default.memo(() => {
|
|
|
379
295
|
<react_native_1.View style={perfStyles.filterRow}>
|
|
380
296
|
<react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{ gap: 6, paddingHorizontal: 12, paddingVertical: 4 }}>
|
|
381
297
|
{[
|
|
382
|
-
{ key: 'ALL', label: '
|
|
298
|
+
{ key: 'ALL', label: t('performance.allLogs'), icon: '⚡', count: events.length },
|
|
383
299
|
{
|
|
384
300
|
key: 'JANKY',
|
|
385
|
-
label: '
|
|
301
|
+
label: t('performance.jankySlow'),
|
|
386
302
|
icon: '⚠️',
|
|
387
303
|
count: events.filter(e => e.severity === 'warning' || e.severity === 'critical').length,
|
|
388
304
|
},
|
|
389
305
|
{
|
|
390
306
|
key: 'NAVIGATION',
|
|
391
|
-
label: '
|
|
307
|
+
label: t('performance.navigation'),
|
|
392
308
|
icon: '🗺️',
|
|
393
309
|
count: events.filter(e => e.category === 'navigation').length,
|
|
394
310
|
},
|
|
395
311
|
{
|
|
396
312
|
key: 'RENDER',
|
|
397
|
-
label: '
|
|
313
|
+
label: t('performance.components'),
|
|
398
314
|
icon: '⚛️',
|
|
399
315
|
count: events.filter(e => e.category === 'render').length,
|
|
400
316
|
},
|
|
401
317
|
{
|
|
402
318
|
key: 'MEMORY',
|
|
403
|
-
label: '
|
|
319
|
+
label: t('performance.memoryGc'),
|
|
404
320
|
icon: '🧠',
|
|
405
321
|
count: events.filter(e => e.category === 'memory').length,
|
|
406
322
|
},
|
|
407
323
|
{
|
|
408
324
|
key: 'IO',
|
|
409
|
-
label: '
|
|
325
|
+
label: t('performance.networkIo'),
|
|
410
326
|
icon: '🌐',
|
|
411
327
|
count: events.filter(e => e.category === 'io' || e.category === 'bridge').length,
|
|
412
328
|
},
|
|
@@ -434,7 +350,7 @@ const PerformanceTab = react_1.default.memo(() => {
|
|
|
434
350
|
<react_native_1.View style={perfStyles.metricCardHeader}>
|
|
435
351
|
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
436
352
|
<NetworkIcons_1.PerformanceIcon color={AppColors_1.AppColors.purple} size={18}/>
|
|
437
|
-
<react_native_1.Text style={perfStyles.metricCardTitle}>
|
|
353
|
+
<react_native_1.Text style={perfStyles.metricCardTitle}>{t('performance.liveFps')}</react_native_1.Text>
|
|
438
354
|
</react_native_1.View>
|
|
439
355
|
<react_native_1.View style={[
|
|
440
356
|
perfStyles.scorePill,
|
|
@@ -456,36 +372,36 @@ const PerformanceTab = react_1.default.memo(() => {
|
|
|
456
372
|
perfStyles.fpsBigNumber,
|
|
457
373
|
{
|
|
458
374
|
color: currentFps >= 55
|
|
459
|
-
?
|
|
375
|
+
? AppColors_1.AppColors.emerald600
|
|
460
376
|
: currentFps >= 40
|
|
461
|
-
?
|
|
462
|
-
:
|
|
377
|
+
? AppColors_1.AppColors.firebaseOrange
|
|
378
|
+
: AppColors_1.AppColors.errorColor,
|
|
463
379
|
},
|
|
464
380
|
]}>
|
|
465
381
|
{currentFps}
|
|
466
382
|
</react_native_1.Text>
|
|
467
|
-
<react_native_1.Text style={perfStyles.fpsUnit}>
|
|
383
|
+
<react_native_1.Text style={perfStyles.fpsUnit}>{t('performance.fpsUnit')}</react_native_1.Text>
|
|
468
384
|
</react_native_1.View>
|
|
469
385
|
|
|
470
386
|
<react_native_1.View style={perfStyles.fpsStatsGrid}>
|
|
471
387
|
<react_native_1.View style={perfStyles.statItem}>
|
|
472
|
-
<react_native_1.Text style={perfStyles.statLabel}>
|
|
388
|
+
<react_native_1.Text style={perfStyles.statLabel}>{t('performance.avgFrameTime')}</react_native_1.Text>
|
|
473
389
|
<react_native_1.Text style={perfStyles.statValue}>{avgFps}</react_native_1.Text>
|
|
474
390
|
</react_native_1.View>
|
|
475
391
|
<react_native_1.View style={perfStyles.statItem}>
|
|
476
|
-
<react_native_1.Text style={perfStyles.statLabel}>
|
|
477
|
-
<react_native_1.Text style={[perfStyles.statValue, minFps < 50 && { color:
|
|
392
|
+
<react_native_1.Text style={perfStyles.statLabel}>{t('performance.peakTime')}</react_native_1.Text>
|
|
393
|
+
<react_native_1.Text style={[perfStyles.statValue, minFps < 50 && { color: AppColors_1.AppColors.firebaseOrange }]}>
|
|
478
394
|
{minFps}
|
|
479
395
|
</react_native_1.Text>
|
|
480
396
|
</react_native_1.View>
|
|
481
397
|
<react_native_1.View style={perfStyles.statItem}>
|
|
482
|
-
<react_native_1.Text style={perfStyles.statLabel}>
|
|
483
|
-
<react_native_1.Text style={[perfStyles.statValue, jsLagMs > 5 && { color:
|
|
398
|
+
<react_native_1.Text style={perfStyles.statLabel}>{t('performance.jsLag')}</react_native_1.Text>
|
|
399
|
+
<react_native_1.Text style={[perfStyles.statValue, jsLagMs > 5 && { color: AppColors_1.AppColors.firebaseOrange }]}>
|
|
484
400
|
{jsLagMs}ms
|
|
485
401
|
</react_native_1.Text>
|
|
486
402
|
</react_native_1.View>
|
|
487
403
|
<react_native_1.View style={perfStyles.statItem}>
|
|
488
|
-
<react_native_1.Text style={perfStyles.statLabel}>
|
|
404
|
+
<react_native_1.Text style={perfStyles.statLabel}>{t('performance.jankRate')}</react_native_1.Text>
|
|
489
405
|
<react_native_1.Text style={perfStyles.statValue}>
|
|
490
406
|
{totalFrames > 0
|
|
491
407
|
? `${((jankyFrameCount / Math.max(1, totalFrames / 60)) * 100).toFixed(0)}%`
|
|
@@ -505,50 +421,73 @@ const PerformanceTab = react_1.default.memo(() => {
|
|
|
505
421
|
perfStyles.sparklineBar,
|
|
506
422
|
{
|
|
507
423
|
height: barHeight,
|
|
508
|
-
backgroundColor: isLow ?
|
|
424
|
+
backgroundColor: isLow ? AppColors_1.AppColors.errorColor : AppColors_1.AppColors.emerald500,
|
|
509
425
|
},
|
|
510
426
|
]}/>
|
|
511
427
|
</react_native_1.View>);
|
|
512
428
|
})}
|
|
513
429
|
</react_native_1.View>
|
|
514
430
|
<react_native_1.View style={perfStyles.sparklineFooter}>
|
|
515
|
-
<react_native_1.Text style={perfStyles.sparklineFooterText}>
|
|
516
|
-
<react_native_1.Text style={perfStyles.sparklineFooterTarget}>
|
|
431
|
+
<react_native_1.Text style={perfStyles.sparklineFooterText}>{t('performance.realtimeWindow')}</react_native_1.Text>
|
|
432
|
+
<react_native_1.Text style={perfStyles.sparklineFooterTarget}>{t('performance.fpsTarget')}</react_native_1.Text>
|
|
517
433
|
</react_native_1.View>
|
|
518
434
|
</react_native_1.View>
|
|
519
435
|
|
|
520
436
|
{/* ── 2. FRAME BUDGET BREAKDOWN CARD ── */}
|
|
521
437
|
<react_native_1.View style={perfStyles.budgetCard}>
|
|
522
438
|
<react_native_1.View style={perfStyles.budgetHeader}>
|
|
523
|
-
<react_native_1.Text style={perfStyles.budgetTitle}>
|
|
524
|
-
<react_native_1.Text style={perfStyles.budgetHeadroom}
|
|
439
|
+
<react_native_1.Text style={perfStyles.budgetTitle}>{t('performance.budgetUsage')}</react_native_1.Text>
|
|
440
|
+
<react_native_1.Text style={perfStyles.budgetHeadroom}>
|
|
441
|
+
{t('performance.budgetHeadroom', {
|
|
442
|
+
time: frameBudgetStats.freeTime,
|
|
443
|
+
percent: frameBudgetStats.headroomPercent,
|
|
444
|
+
})}
|
|
445
|
+
</react_native_1.Text>
|
|
525
446
|
</react_native_1.View>
|
|
526
447
|
|
|
527
448
|
{/* Multi-colored segmented frame budget bar */}
|
|
528
449
|
<react_native_1.View style={perfStyles.budgetBarContainer}>
|
|
529
|
-
<react_native_1.View style={[
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
450
|
+
<react_native_1.View style={[
|
|
451
|
+
perfStyles.budgetBarSegment,
|
|
452
|
+
{ flex: Math.max(0.5, frameBudgetStats.jsTime), backgroundColor: AppColors_1.AppColors.sky400 },
|
|
453
|
+
]}/>
|
|
454
|
+
<react_native_1.View style={[
|
|
455
|
+
perfStyles.budgetBarSegment,
|
|
456
|
+
{ flex: Math.max(0.5, frameBudgetStats.layoutTime), backgroundColor: AppColors_1.AppColors.indigo500 },
|
|
457
|
+
]}/>
|
|
458
|
+
<react_native_1.View style={[
|
|
459
|
+
perfStyles.budgetBarSegment,
|
|
460
|
+
{ flex: Math.max(0.5, frameBudgetStats.renderTime), backgroundColor: AppColors_1.AppColors.pink400 },
|
|
461
|
+
]}/>
|
|
462
|
+
<react_native_1.View style={[
|
|
463
|
+
perfStyles.budgetBarSegment,
|
|
464
|
+
{ flex: Math.max(0.5, frameBudgetStats.freeTime), backgroundColor: AppColors_1.AppColors.emerald400 },
|
|
465
|
+
]}/>
|
|
533
466
|
</react_native_1.View>
|
|
534
467
|
|
|
535
468
|
<react_native_1.View style={perfStyles.budgetLegendGrid}>
|
|
536
469
|
<react_native_1.View style={perfStyles.legendItem}>
|
|
537
|
-
<react_native_1.View style={[perfStyles.legendDot, { backgroundColor:
|
|
538
|
-
<react_native_1.Text style={perfStyles.legendText}>
|
|
470
|
+
<react_native_1.View style={[perfStyles.legendDot, { backgroundColor: AppColors_1.AppColors.sky400 }]}/>
|
|
471
|
+
<react_native_1.Text style={perfStyles.legendText}>
|
|
472
|
+
{t('performance.jsExec', { time: frameBudgetStats.jsTime })}
|
|
473
|
+
</react_native_1.Text>
|
|
539
474
|
</react_native_1.View>
|
|
540
475
|
<react_native_1.View style={perfStyles.legendItem}>
|
|
541
|
-
<react_native_1.View style={[perfStyles.legendDot, { backgroundColor:
|
|
542
|
-
<react_native_1.Text style={perfStyles.legendText}>
|
|
476
|
+
<react_native_1.View style={[perfStyles.legendDot, { backgroundColor: AppColors_1.AppColors.indigo500 }]}/>
|
|
477
|
+
<react_native_1.Text style={perfStyles.legendText}>
|
|
478
|
+
{t('performance.yogaLayoutTime', { time: frameBudgetStats.layoutTime })}
|
|
479
|
+
</react_native_1.Text>
|
|
543
480
|
</react_native_1.View>
|
|
544
481
|
<react_native_1.View style={perfStyles.legendItem}>
|
|
545
|
-
<react_native_1.View style={[perfStyles.legendDot, { backgroundColor:
|
|
546
|
-
<react_native_1.Text style={perfStyles.legendText}>
|
|
482
|
+
<react_native_1.View style={[perfStyles.legendDot, { backgroundColor: AppColors_1.AppColors.pink400 }]}/>
|
|
483
|
+
<react_native_1.Text style={perfStyles.legendText}>
|
|
484
|
+
{t('performance.uiRenderTime', { time: frameBudgetStats.renderTime })}
|
|
485
|
+
</react_native_1.Text>
|
|
547
486
|
</react_native_1.View>
|
|
548
487
|
<react_native_1.View style={perfStyles.legendItem}>
|
|
549
|
-
<react_native_1.View style={[perfStyles.legendDot, { backgroundColor:
|
|
550
|
-
<react_native_1.Text style={[perfStyles.legendText, { color:
|
|
551
|
-
|
|
488
|
+
<react_native_1.View style={[perfStyles.legendDot, { backgroundColor: AppColors_1.AppColors.emerald400 }]}/>
|
|
489
|
+
<react_native_1.Text style={[perfStyles.legendText, { color: AppColors_1.AppColors.emerald600, fontFamily: AppFonts_1.AppFonts.interBold }]}>
|
|
490
|
+
{t('performance.freeTime', { time: frameBudgetStats.freeTime })}
|
|
552
491
|
</react_native_1.Text>
|
|
553
492
|
</react_native_1.View>
|
|
554
493
|
</react_native_1.View>
|
|
@@ -557,49 +496,51 @@ const PerformanceTab = react_1.default.memo(() => {
|
|
|
557
496
|
{/* ── 3. RUNTIME ENGINE & MEMORY SUMMARY ── */}
|
|
558
497
|
<react_native_1.View style={perfStyles.engineSummaryGrid}>
|
|
559
498
|
<react_native_1.View style={perfStyles.engineSummaryCard}>
|
|
560
|
-
<react_native_1.Text style={perfStyles.engineSummaryLabel}>
|
|
561
|
-
<react_native_1.Text style={perfStyles.engineSummaryValue}>
|
|
562
|
-
<react_native_1.Text style={perfStyles.engineSummarySub}>
|
|
499
|
+
<react_native_1.Text style={perfStyles.engineSummaryLabel}>{t('performance.jsEngine')}</react_native_1.Text>
|
|
500
|
+
<react_native_1.Text style={perfStyles.engineSummaryValue}>{runtimeDiagnostics.jsEngineName}</react_native_1.Text>
|
|
501
|
+
<react_native_1.Text style={perfStyles.engineSummarySub}>{runtimeDiagnostics.jsEngineSub}</react_native_1.Text>
|
|
563
502
|
</react_native_1.View>
|
|
564
503
|
<react_native_1.View style={perfStyles.engineSummaryCard}>
|
|
565
|
-
<react_native_1.Text style={perfStyles.engineSummaryLabel}>
|
|
566
|
-
<react_native_1.Text style={perfStyles.engineSummaryValue}>
|
|
567
|
-
<react_native_1.Text style={perfStyles.engineSummarySub}>
|
|
504
|
+
<react_native_1.Text style={perfStyles.engineSummaryLabel}>{t('performance.uiRenderThread')}</react_native_1.Text>
|
|
505
|
+
<react_native_1.Text style={perfStyles.engineSummaryValue}>{runtimeDiagnostics.uiArchName}</react_native_1.Text>
|
|
506
|
+
<react_native_1.Text style={perfStyles.engineSummarySub}>{runtimeDiagnostics.uiArchSub}</react_native_1.Text>
|
|
568
507
|
</react_native_1.View>
|
|
569
508
|
<react_native_1.View style={perfStyles.engineSummaryCard}>
|
|
570
|
-
<react_native_1.Text style={perfStyles.engineSummaryLabel}>
|
|
571
|
-
<react_native_1.Text style={perfStyles.engineSummaryValue}>
|
|
572
|
-
<react_native_1.Text style={perfStyles.engineSummarySub}>
|
|
509
|
+
<react_native_1.Text style={perfStyles.engineSummaryLabel}>{t('performance.tabMemory')}</react_native_1.Text>
|
|
510
|
+
<react_native_1.Text style={perfStyles.engineSummaryValue}>{runtimeDiagnostics.usedHeapMb} MB</react_native_1.Text>
|
|
511
|
+
<react_native_1.Text style={perfStyles.engineSummarySub}>
|
|
512
|
+
{t('performance.heapAllocatedSub', { allocated: runtimeDiagnostics.totalAllocMb })}
|
|
513
|
+
</react_native_1.Text>
|
|
573
514
|
</react_native_1.View>
|
|
574
515
|
</react_native_1.View>
|
|
575
516
|
|
|
576
517
|
{/* ── 4. PERFORMANCE LOGS & DETAILED EVENTS ── */}
|
|
577
518
|
<react_native_1.View style={perfStyles.logsHeaderRow}>
|
|
578
519
|
<react_native_1.Text style={perfStyles.logsSectionHeading}>
|
|
579
|
-
|
|
520
|
+
{t('performance.recordedEvents')} ({filteredEvents.length})
|
|
580
521
|
</react_native_1.Text>
|
|
581
522
|
{events.length > 0 && (<TouchableScale_1.default onPress={clearEvents}>
|
|
582
|
-
<react_native_1.Text style={perfStyles.clearLink}>
|
|
523
|
+
<react_native_1.Text style={perfStyles.clearLink}>{t('common.clear')}</react_native_1.Text>
|
|
583
524
|
</TouchableScale_1.default>)}
|
|
584
525
|
</react_native_1.View>
|
|
585
526
|
|
|
586
527
|
{filteredEvents.length === 0 ? (<react_native_1.View style={perfStyles.emptyCard}>
|
|
587
528
|
<react_native_1.Text style={{ fontSize: 28 }}>⚡</react_native_1.Text>
|
|
588
|
-
<react_native_1.Text style={perfStyles.emptyTitle}>
|
|
529
|
+
<react_native_1.Text style={perfStyles.emptyTitle}>{t('performance.emptyTitle')}</react_native_1.Text>
|
|
589
530
|
<react_native_1.Text style={perfStyles.emptySub}>
|
|
590
|
-
|
|
531
|
+
{t('performance.emptySubtitle')}
|
|
591
532
|
</react_native_1.Text>
|
|
592
533
|
</react_native_1.View>) : (filteredEvents.map(event => {
|
|
593
534
|
const isOptimal = event.severity === 'optimal';
|
|
594
535
|
const isWarning = event.severity === 'warning';
|
|
595
536
|
const isCritical = event.severity === 'critical';
|
|
596
537
|
const isExpanded = !!expandedEventIds[event.id];
|
|
597
|
-
const badgeBg = isOptimal ?
|
|
598
|
-
const badgeBorder = isOptimal ?
|
|
599
|
-
const badgeColor = isOptimal ?
|
|
538
|
+
const badgeBg = isOptimal ? AppColors_1.AppColors.greenBg : isWarning ? AppColors_1.AppColors.amberBg : AppColors_1.AppColors.errorCardBg;
|
|
539
|
+
const badgeBorder = isOptimal ? AppColors_1.AppColors.greenBorder : isWarning ? AppColors_1.AppColors.lightOrange : AppColors_1.AppColors.errorBorder;
|
|
540
|
+
const badgeColor = isOptimal ? AppColors_1.AppColors.emerald600 : isWarning ? AppColors_1.AppColors.amber700 : AppColors_1.AppColors.errorColor;
|
|
600
541
|
return (<TouchableScale_1.default key={event.id} onPress={() => toggleEventExpand(event.id)} style={[
|
|
601
542
|
perfStyles.eventCard,
|
|
602
|
-
isCritical && { borderColor:
|
|
543
|
+
isCritical && { borderColor: AppColors_1.AppColors.errorBorder, backgroundColor: AppColors_1.AppColors.errorCardBg },
|
|
603
544
|
]}>
|
|
604
545
|
<react_native_1.View style={perfStyles.eventTopRow}>
|
|
605
546
|
<react_native_1.View style={[
|
|
@@ -614,12 +555,12 @@ const PerformanceTab = react_1.default.memo(() => {
|
|
|
614
555
|
<react_native_1.View style={{ flex: 1, paddingHorizontal: 6 }}>
|
|
615
556
|
<HighlightText_1.default text={event.label} search={search} style={perfStyles.eventLabel} highlightStyle={perfStyles.searchHighlight}/>
|
|
616
557
|
<react_native_1.Text style={perfStyles.eventMeta}>
|
|
617
|
-
{event.durationMs
|
|
558
|
+
{t('performance.msTotal', { duration: event.durationMs, time: new Date(event.timestamp).toLocaleTimeString() })}
|
|
618
559
|
</react_native_1.Text>
|
|
619
560
|
</react_native_1.View>
|
|
620
561
|
|
|
621
562
|
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
622
|
-
<CopyButton_1.default value={() => event} label=
|
|
563
|
+
<CopyButton_1.default value={() => event} label={t('common.copyJson')}/>
|
|
623
564
|
<react_native_1.Text style={perfStyles.expandChevron}>
|
|
624
565
|
{isExpanded ? '▲' : '▼'}
|
|
625
566
|
</react_native_1.Text>
|
|
@@ -632,7 +573,7 @@ const PerformanceTab = react_1.default.memo(() => {
|
|
|
632
573
|
{isExpanded && (<react_native_1.View style={perfStyles.expandedDetailBox}>
|
|
633
574
|
{/* Source file / hook tag */}
|
|
634
575
|
{event.source && (<react_native_1.View style={perfStyles.sourceRow}>
|
|
635
|
-
<react_native_1.Text style={perfStyles.sourceTag}>
|
|
576
|
+
<react_native_1.Text style={perfStyles.sourceTag}>{t('common.source')}</react_native_1.Text>
|
|
636
577
|
<react_native_1.Text style={perfStyles.sourceText} numberOfLines={1}>
|
|
637
578
|
{event.source}
|
|
638
579
|
</react_native_1.Text>
|
|
@@ -641,28 +582,28 @@ const PerformanceTab = react_1.default.memo(() => {
|
|
|
641
582
|
{/* Thread Timing Breakdown */}
|
|
642
583
|
{event.breakdown && (<react_native_1.View style={perfStyles.breakdownGrid}>
|
|
643
584
|
<react_native_1.View style={perfStyles.breakdownCol}>
|
|
644
|
-
<react_native_1.Text style={perfStyles.breakdownLabel}>
|
|
585
|
+
<react_native_1.Text style={perfStyles.breakdownLabel}>{t('performance.jsThread')}</react_native_1.Text>
|
|
645
586
|
<react_native_1.Text style={perfStyles.breakdownVal}>
|
|
646
587
|
{event.breakdown.jsTimeMs} ms
|
|
647
588
|
</react_native_1.Text>
|
|
648
589
|
</react_native_1.View>
|
|
649
590
|
<react_native_1.View style={perfStyles.breakdownCol}>
|
|
650
|
-
<react_native_1.Text style={perfStyles.breakdownLabel}>
|
|
591
|
+
<react_native_1.Text style={perfStyles.breakdownLabel}>{t('performance.uiThread')}</react_native_1.Text>
|
|
651
592
|
<react_native_1.Text style={perfStyles.breakdownVal}>
|
|
652
593
|
{event.breakdown.uiTimeMs} ms
|
|
653
594
|
</react_native_1.Text>
|
|
654
595
|
</react_native_1.View>
|
|
655
596
|
{event.breakdown.bridgeLatencyMs != null && (<react_native_1.View style={perfStyles.breakdownCol}>
|
|
656
|
-
<react_native_1.Text style={perfStyles.breakdownLabel}>
|
|
597
|
+
<react_native_1.Text style={perfStyles.breakdownLabel}>{t('performance.jsiLatency')}</react_native_1.Text>
|
|
657
598
|
<react_native_1.Text style={perfStyles.breakdownVal}>
|
|
658
599
|
{event.breakdown.bridgeLatencyMs} ms
|
|
659
600
|
</react_native_1.Text>
|
|
660
601
|
</react_native_1.View>)}
|
|
661
602
|
{event.heapDeltaKb != null && (<react_native_1.View style={perfStyles.breakdownCol}>
|
|
662
|
-
<react_native_1.Text style={perfStyles.breakdownLabel}>
|
|
603
|
+
<react_native_1.Text style={perfStyles.breakdownLabel}>{t('performance.heapImpact')}</react_native_1.Text>
|
|
663
604
|
<react_native_1.Text style={[
|
|
664
605
|
perfStyles.breakdownVal,
|
|
665
|
-
{ color: event.heapDeltaKb > 0 ?
|
|
606
|
+
{ color: event.heapDeltaKb > 0 ? AppColors_1.AppColors.amber700 : AppColors_1.AppColors.emerald600 },
|
|
666
607
|
]}>
|
|
667
608
|
{event.heapDeltaKb > 0 ? `+${event.heapDeltaKb}` : event.heapDeltaKb} KB
|
|
668
609
|
</react_native_1.Text>
|
|
@@ -671,14 +612,14 @@ const PerformanceTab = react_1.default.memo(() => {
|
|
|
671
612
|
|
|
672
613
|
{/* Actionable Optimization Tip */}
|
|
673
614
|
{event.advice && (<react_native_1.View style={perfStyles.adviceCard}>
|
|
674
|
-
<react_native_1.Text style={perfStyles.adviceHeading}>💡
|
|
615
|
+
<react_native_1.Text style={perfStyles.adviceHeading}>💡 {t('performance.optimizationTip')}</react_native_1.Text>
|
|
675
616
|
<react_native_1.Text style={perfStyles.adviceBodyText}>{event.advice}</react_native_1.Text>
|
|
676
617
|
</react_native_1.View>)}
|
|
677
618
|
</react_native_1.View>)}
|
|
678
619
|
</TouchableScale_1.default>);
|
|
679
620
|
}))}
|
|
680
621
|
|
|
681
|
-
<EndOfListFooter_1.default count={filteredEvents.length} label=
|
|
622
|
+
<EndOfListFooter_1.default count={filteredEvents.length} label={t('performance.recordedEvents')}/>
|
|
682
623
|
</react_native_1.ScrollView>
|
|
683
624
|
</react_native_1.View>);
|
|
684
625
|
});
|
|
@@ -726,12 +667,12 @@ const perfStyles = react_native_1.StyleSheet.create({
|
|
|
726
667
|
borderWidth: 1,
|
|
727
668
|
},
|
|
728
669
|
recordBtnActive: {
|
|
729
|
-
backgroundColor:
|
|
730
|
-
borderColor:
|
|
670
|
+
backgroundColor: AppColors_1.AppColors.greenBg,
|
|
671
|
+
borderColor: AppColors_1.AppColors.greenBorder,
|
|
731
672
|
},
|
|
732
673
|
recordBtnPaused: {
|
|
733
|
-
backgroundColor:
|
|
734
|
-
borderColor:
|
|
674
|
+
backgroundColor: AppColors_1.AppColors.amberBg,
|
|
675
|
+
borderColor: AppColors_1.AppColors.lightOrange,
|
|
735
676
|
},
|
|
736
677
|
recordDot: {
|
|
737
678
|
width: 6,
|
|
@@ -890,7 +831,7 @@ const perfStyles = react_native_1.StyleSheet.create({
|
|
|
890
831
|
sparklineFooterTarget: {
|
|
891
832
|
fontFamily: AppFonts_1.AppFonts.interMedium,
|
|
892
833
|
fontSize: 10,
|
|
893
|
-
color:
|
|
834
|
+
color: AppColors_1.AppColors.emerald600,
|
|
894
835
|
},
|
|
895
836
|
budgetCard: {
|
|
896
837
|
backgroundColor: AppColors_1.AppColors.white,
|
|
@@ -913,7 +854,7 @@ const perfStyles = react_native_1.StyleSheet.create({
|
|
|
913
854
|
budgetHeadroom: {
|
|
914
855
|
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
915
856
|
fontSize: 11,
|
|
916
|
-
color:
|
|
857
|
+
color: AppColors_1.AppColors.emerald600,
|
|
917
858
|
},
|
|
918
859
|
budgetBarContainer: {
|
|
919
860
|
flexDirection: 'row',
|
|
@@ -1094,27 +1035,27 @@ const perfStyles = react_native_1.StyleSheet.create({
|
|
|
1094
1035
|
marginTop: 1,
|
|
1095
1036
|
},
|
|
1096
1037
|
adviceCard: {
|
|
1097
|
-
backgroundColor:
|
|
1038
|
+
backgroundColor: AppColors_1.AppColors.purpleTintBg,
|
|
1098
1039
|
borderRadius: 6,
|
|
1099
1040
|
padding: 6,
|
|
1100
1041
|
borderWidth: 1,
|
|
1101
|
-
borderColor:
|
|
1042
|
+
borderColor: AppColors_1.AppColors.purpleBorder,
|
|
1102
1043
|
},
|
|
1103
1044
|
adviceHeading: {
|
|
1104
1045
|
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
1105
1046
|
fontSize: 10,
|
|
1106
|
-
color:
|
|
1047
|
+
color: AppColors_1.AppColors.purpleShade700,
|
|
1107
1048
|
},
|
|
1108
1049
|
adviceBodyText: {
|
|
1109
1050
|
fontFamily: AppFonts_1.AppFonts.interRegular,
|
|
1110
1051
|
fontSize: 10.5,
|
|
1111
|
-
color:
|
|
1052
|
+
color: AppColors_1.AppColors.purple,
|
|
1112
1053
|
lineHeight: 14,
|
|
1113
1054
|
marginTop: 1,
|
|
1114
1055
|
},
|
|
1115
1056
|
searchHighlight: {
|
|
1116
|
-
backgroundColor:
|
|
1117
|
-
color:
|
|
1057
|
+
backgroundColor: AppColors_1.AppColors.yellowHighlight,
|
|
1058
|
+
color: AppColors_1.AppColors.amber800,
|
|
1118
1059
|
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
1119
1060
|
},
|
|
1120
1061
|
emptyCard: {
|