@buoy-gg/highlight-updates 7.0.27 → 7.0.29
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/lib/commonjs/highlight-updates/components/HighlightFilterView.js +102 -0
- package/lib/commonjs/highlight-updates/components/HighlightUpdatesModal.js +5 -1
- package/lib/commonjs/highlight-updates/components/IdentifierBadge.js +7 -1
- package/lib/commonjs/highlight-updates/components/IsolatedRenderList.js +6 -0
- package/lib/commonjs/highlight-updates/components/ModalHeaderContent.js +26 -3
- package/lib/commonjs/highlight-updates/components/RenderCauseBadge.js +7 -1
- package/lib/commonjs/highlight-updates/components/RenderDetailView.js +40 -1
- package/lib/commonjs/highlight-updates/components/RenderHistoryViewer.js +29 -6
- package/lib/commonjs/highlight-updates/components/RenderListItem.js +15 -0
- package/lib/commonjs/highlight-updates/components/RendersCopySettingsView.js +11 -0
- package/lib/commonjs/highlight-updates/components/StatsDisplay.js +3 -0
- package/lib/commonjs/highlight-updates/utils/CommitProfiler.js +6 -1
- package/lib/commonjs/highlight-updates/utils/HighlightUpdatesController.js +65 -3
- package/lib/commonjs/highlight-updates/utils/RenderCauseDetector.js +15 -3
- package/lib/commonjs/highlight-updates/utils/RenderTracker.js +6 -1
- package/lib/commonjs/highlight-updates/utils/namedComposite.js +41 -0
- package/lib/commonjs/highlight-updates/utils/ownStateChanged.js +103 -0
- package/lib/commonjs/highlight-updates/utils/screenElements.js +50 -25
- package/lib/commonjs/highlight-updates/utils/tapMatch.js +58 -0
- package/lib/commonjs/highlight-updates/utils/testIDs.js +68 -0
- package/lib/commonjs/index.js +34 -0
- package/lib/module/highlight-updates/components/HighlightFilterView.js +102 -0
- package/lib/module/highlight-updates/components/HighlightUpdatesModal.js +5 -1
- package/lib/module/highlight-updates/components/IdentifierBadge.js +7 -1
- package/lib/module/highlight-updates/components/IsolatedRenderList.js +6 -0
- package/lib/module/highlight-updates/components/ModalHeaderContent.js +26 -3
- package/lib/module/highlight-updates/components/RenderCauseBadge.js +7 -1
- package/lib/module/highlight-updates/components/RenderDetailView.js +40 -1
- package/lib/module/highlight-updates/components/RenderHistoryViewer.js +29 -6
- package/lib/module/highlight-updates/components/RenderListItem.js +15 -0
- package/lib/module/highlight-updates/components/RendersCopySettingsView.js +11 -0
- package/lib/module/highlight-updates/components/StatsDisplay.js +3 -0
- package/lib/module/highlight-updates/utils/CommitProfiler.js +5 -1
- package/lib/module/highlight-updates/utils/HighlightUpdatesController.js +65 -3
- package/lib/module/highlight-updates/utils/RenderCauseDetector.js +15 -3
- package/lib/module/highlight-updates/utils/RenderTracker.js +6 -1
- package/lib/module/highlight-updates/utils/namedComposite.js +36 -0
- package/lib/module/highlight-updates/utils/ownStateChanged.js +98 -0
- package/lib/module/highlight-updates/utils/screenElements.js +50 -25
- package/lib/module/highlight-updates/utils/tapMatch.js +52 -0
- package/lib/module/highlight-updates/utils/testIDs.js +60 -0
- package/lib/module/index.js +5 -1
- package/lib/typescript/highlight-updates/components/HighlightFilterView.d.ts.map +1 -1
- package/lib/typescript/highlight-updates/components/HighlightUpdatesModal.d.ts.map +1 -1
- package/lib/typescript/highlight-updates/components/IdentifierBadge.d.ts +7 -1
- package/lib/typescript/highlight-updates/components/IdentifierBadge.d.ts.map +1 -1
- package/lib/typescript/highlight-updates/components/IsolatedRenderList.d.ts.map +1 -1
- package/lib/typescript/highlight-updates/components/ModalHeaderContent.d.ts.map +1 -1
- package/lib/typescript/highlight-updates/components/RenderCauseBadge.d.ts +8 -1
- package/lib/typescript/highlight-updates/components/RenderCauseBadge.d.ts.map +1 -1
- package/lib/typescript/highlight-updates/components/RenderDetailView.d.ts.map +1 -1
- package/lib/typescript/highlight-updates/components/RenderHistoryViewer.d.ts.map +1 -1
- package/lib/typescript/highlight-updates/components/RenderListItem.d.ts.map +1 -1
- package/lib/typescript/highlight-updates/components/RendersCopySettingsView.d.ts.map +1 -1
- package/lib/typescript/highlight-updates/components/StatsDisplay.d.ts.map +1 -1
- package/lib/typescript/highlight-updates/utils/CommitProfiler.d.ts.map +1 -1
- package/lib/typescript/highlight-updates/utils/HighlightUpdatesController.d.ts.map +1 -1
- package/lib/typescript/highlight-updates/utils/RenderCauseDetector.d.ts.map +1 -1
- package/lib/typescript/highlight-updates/utils/RenderTracker.d.ts +6 -0
- package/lib/typescript/highlight-updates/utils/RenderTracker.d.ts.map +1 -1
- package/lib/typescript/highlight-updates/utils/namedComposite.d.ts +17 -0
- package/lib/typescript/highlight-updates/utils/namedComposite.d.ts.map +1 -0
- package/lib/typescript/highlight-updates/utils/ownStateChanged.d.ts +66 -0
- package/lib/typescript/highlight-updates/utils/ownStateChanged.d.ts.map +1 -0
- package/lib/typescript/highlight-updates/utils/screenElements.d.ts.map +1 -1
- package/lib/typescript/highlight-updates/utils/tapMatch.d.ts +42 -0
- package/lib/typescript/highlight-updates/utils/tapMatch.d.ts.map +1 -0
- package/lib/typescript/highlight-updates/utils/testIDs.d.ts +44 -0
- package/lib/typescript/highlight-updates/utils/testIDs.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +1 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/package.json +7 -7
|
@@ -89,21 +89,25 @@ export function RenderDetailView({
|
|
|
89
89
|
children: [/*#__PURE__*/_jsxs(View, {
|
|
90
90
|
style: styles.headerLeft,
|
|
91
91
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
92
|
+
testID: "buoy-highlight-detail-name",
|
|
92
93
|
style: styles.componentName,
|
|
93
94
|
numberOfLines: 1,
|
|
94
95
|
children: componentName
|
|
95
96
|
}), /*#__PURE__*/_jsx(View, {
|
|
96
97
|
style: styles.nativeTypeBadge,
|
|
97
98
|
children: /*#__PURE__*/_jsx(Text, {
|
|
99
|
+
testID: "buoy-highlight-detail-type",
|
|
98
100
|
style: styles.nativeTypeText,
|
|
99
101
|
children: nativeType
|
|
100
102
|
})
|
|
101
103
|
})]
|
|
102
104
|
}), /*#__PURE__*/_jsx(CopyButton, {
|
|
103
105
|
value: copyData,
|
|
104
|
-
size: 14
|
|
106
|
+
size: 14,
|
|
107
|
+
testID: "buoy-highlight-detail-copy"
|
|
105
108
|
})]
|
|
106
109
|
}), /*#__PURE__*/_jsxs(ScrollView, {
|
|
110
|
+
testID: "buoy-highlight-detail-scroll",
|
|
107
111
|
style: styles.scrollView,
|
|
108
112
|
contentContainerStyle: [styles.scrollContent, showHistoryFooter && {
|
|
109
113
|
paddingBottom: 100
|
|
@@ -116,11 +120,13 @@ export function RenderDetailView({
|
|
|
116
120
|
render: render,
|
|
117
121
|
rendersPerSec: rendersPerSec
|
|
118
122
|
}), hiddenEventCount > 0 && /*#__PURE__*/_jsxs(View, {
|
|
123
|
+
testID: "buoy-highlight-detail-locked",
|
|
119
124
|
style: styles.lockedBanner,
|
|
120
125
|
children: [/*#__PURE__*/_jsx(Lock, {
|
|
121
126
|
size: 14,
|
|
122
127
|
color: night.color.warning
|
|
123
128
|
}), /*#__PURE__*/_jsxs(Text, {
|
|
129
|
+
testID: "buoy-highlight-detail-locked-text",
|
|
124
130
|
style: styles.lockedBannerText,
|
|
125
131
|
children: [hiddenEventCount, " ", hiddenEventCount === 1 ? 'event' : 'events', " hidden"]
|
|
126
132
|
}), /*#__PURE__*/_jsx(Text, {
|
|
@@ -165,10 +171,12 @@ function AnswerCard({
|
|
|
165
171
|
return "Changed:";
|
|
166
172
|
};
|
|
167
173
|
return /*#__PURE__*/_jsxs(View, {
|
|
174
|
+
testID: "buoy-highlight-detail-cause",
|
|
168
175
|
style: styles.answerCard,
|
|
169
176
|
children: [/*#__PURE__*/_jsxs(View, {
|
|
170
177
|
style: styles.causeBadgeRow,
|
|
171
178
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
179
|
+
testID: "buoy-highlight-detail-cause-label",
|
|
172
180
|
style: styles.causeLabel,
|
|
173
181
|
children: getLabel()
|
|
174
182
|
}), /*#__PURE__*/_jsx(View, {
|
|
@@ -176,6 +184,7 @@ function AnswerCard({
|
|
|
176
184
|
backgroundColor: config.color + "20"
|
|
177
185
|
}],
|
|
178
186
|
children: /*#__PURE__*/_jsx(Text, {
|
|
187
|
+
testID: "buoy-highlight-detail-cause-badge",
|
|
179
188
|
style: [styles.causeBadgeLargeText, {
|
|
180
189
|
color: config.color
|
|
181
190
|
}],
|
|
@@ -207,6 +216,7 @@ function AnswerCard({
|
|
|
207
216
|
children: cause.changedKeys.filter(k => !k.includes("(ref only)")).slice(0, 5).map((key, index) => /*#__PURE__*/_jsx(View, {
|
|
208
217
|
style: styles.propChangeChip,
|
|
209
218
|
children: /*#__PURE__*/_jsx(Text, {
|
|
219
|
+
testID: `buoy-highlight-detail-changed-${index}`,
|
|
210
220
|
style: styles.propChangeText,
|
|
211
221
|
children: key
|
|
212
222
|
})
|
|
@@ -228,6 +238,7 @@ function DetailsSection({
|
|
|
228
238
|
return /*#__PURE__*/_jsxs(View, {
|
|
229
239
|
style: styles.detailsSection,
|
|
230
240
|
children: [hasIdentifiers && /*#__PURE__*/_jsxs(View, {
|
|
241
|
+
testID: "buoy-highlight-detail-identifiers",
|
|
231
242
|
style: styles.detailsCard,
|
|
232
243
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
233
244
|
style: styles.detailsCardTitle,
|
|
@@ -243,10 +254,13 @@ function DetailsSection({
|
|
|
243
254
|
value: render.accessibilityLabel
|
|
244
255
|
})]
|
|
245
256
|
}), /*#__PURE__*/_jsxs(View, {
|
|
257
|
+
testID: "buoy-highlight-detail-stats",
|
|
246
258
|
style: styles.statsRow,
|
|
247
259
|
children: [/*#__PURE__*/_jsxs(View, {
|
|
260
|
+
testID: "buoy-highlight-detail-stat-renders",
|
|
248
261
|
style: styles.statItem,
|
|
249
262
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
263
|
+
testID: "buoy-highlight-detail-stat-renders-value",
|
|
250
264
|
style: [styles.statValue, {
|
|
251
265
|
color: render.color
|
|
252
266
|
}],
|
|
@@ -258,8 +272,10 @@ function DetailsSection({
|
|
|
258
272
|
}), /*#__PURE__*/_jsx(View, {
|
|
259
273
|
style: styles.statDivider
|
|
260
274
|
}), /*#__PURE__*/_jsxs(View, {
|
|
275
|
+
testID: "buoy-highlight-detail-stat-rate",
|
|
261
276
|
style: styles.statItem,
|
|
262
277
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
278
|
+
testID: "buoy-highlight-detail-stat-rate-value",
|
|
263
279
|
style: styles.statValue,
|
|
264
280
|
children: rendersPerSec
|
|
265
281
|
}), /*#__PURE__*/_jsx(Text, {
|
|
@@ -269,8 +285,10 @@ function DetailsSection({
|
|
|
269
285
|
}), /*#__PURE__*/_jsx(View, {
|
|
270
286
|
style: styles.statDivider
|
|
271
287
|
}), /*#__PURE__*/_jsxs(View, {
|
|
288
|
+
testID: "buoy-highlight-detail-stat-tag",
|
|
272
289
|
style: styles.statItem,
|
|
273
290
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
291
|
+
testID: "buoy-highlight-detail-stat-tag-value",
|
|
274
292
|
style: styles.statValue,
|
|
275
293
|
children: render.nativeTag
|
|
276
294
|
}), /*#__PURE__*/_jsx(Text, {
|
|
@@ -279,6 +297,7 @@ function DetailsSection({
|
|
|
279
297
|
})]
|
|
280
298
|
})]
|
|
281
299
|
}), hasMeasurements && /*#__PURE__*/_jsxs(View, {
|
|
300
|
+
testID: "buoy-highlight-detail-measure",
|
|
282
301
|
style: styles.measurementsRow,
|
|
283
302
|
children: [/*#__PURE__*/_jsxs(View, {
|
|
284
303
|
style: styles.measurementItem,
|
|
@@ -286,6 +305,7 @@ function DetailsSection({
|
|
|
286
305
|
style: styles.measurementLabel,
|
|
287
306
|
children: "x"
|
|
288
307
|
}), /*#__PURE__*/_jsx(Text, {
|
|
308
|
+
testID: "buoy-highlight-detail-measure-x",
|
|
289
309
|
style: styles.measurementValue,
|
|
290
310
|
children: Math.round(render.measurements.x)
|
|
291
311
|
})]
|
|
@@ -295,6 +315,7 @@ function DetailsSection({
|
|
|
295
315
|
style: styles.measurementLabel,
|
|
296
316
|
children: "y"
|
|
297
317
|
}), /*#__PURE__*/_jsx(Text, {
|
|
318
|
+
testID: "buoy-highlight-detail-measure-y",
|
|
298
319
|
style: styles.measurementValue,
|
|
299
320
|
children: Math.round(render.measurements.y)
|
|
300
321
|
})]
|
|
@@ -304,6 +325,7 @@ function DetailsSection({
|
|
|
304
325
|
style: styles.measurementLabel,
|
|
305
326
|
children: "w"
|
|
306
327
|
}), /*#__PURE__*/_jsx(Text, {
|
|
328
|
+
testID: "buoy-highlight-detail-measure-w",
|
|
307
329
|
style: styles.measurementValue,
|
|
308
330
|
children: Math.round(render.measurements.width)
|
|
309
331
|
})]
|
|
@@ -313,6 +335,7 @@ function DetailsSection({
|
|
|
313
335
|
style: styles.measurementLabel,
|
|
314
336
|
children: "h"
|
|
315
337
|
}), /*#__PURE__*/_jsx(Text, {
|
|
338
|
+
testID: "buoy-highlight-detail-measure-h",
|
|
316
339
|
style: styles.measurementValue,
|
|
317
340
|
children: Math.round(render.measurements.height)
|
|
318
341
|
})]
|
|
@@ -328,12 +351,15 @@ function DetailRow({
|
|
|
328
351
|
label,
|
|
329
352
|
value
|
|
330
353
|
}) {
|
|
354
|
+
const handle = `buoy-highlight-detail-id-${label.toLowerCase()}`;
|
|
331
355
|
return /*#__PURE__*/_jsxs(View, {
|
|
356
|
+
testID: handle,
|
|
332
357
|
style: styles.detailRow,
|
|
333
358
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
334
359
|
style: styles.detailLabel,
|
|
335
360
|
children: label
|
|
336
361
|
}), /*#__PURE__*/_jsx(Text, {
|
|
362
|
+
testID: `${handle}-value`,
|
|
337
363
|
style: styles.detailValue,
|
|
338
364
|
numberOfLines: 1,
|
|
339
365
|
children: value
|
|
@@ -415,6 +441,7 @@ function QuickActionsSection({
|
|
|
415
441
|
}
|
|
416
442
|
}, [selectedOption, onAddFilter]);
|
|
417
443
|
return /*#__PURE__*/_jsxs(View, {
|
|
444
|
+
testID: "buoy-highlight-quick",
|
|
418
445
|
style: styles.quickActionsSection,
|
|
419
446
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
420
447
|
style: styles.quickActionsTitle,
|
|
@@ -422,6 +449,7 @@ function QuickActionsSection({
|
|
|
422
449
|
}), /*#__PURE__*/_jsx(View, {
|
|
423
450
|
style: styles.filterOptionsList,
|
|
424
451
|
children: filterOptions.map((option, index) => /*#__PURE__*/_jsx(FilterOptionCard, {
|
|
452
|
+
testID: `buoy-highlight-quick-${option.type.toLowerCase()}`,
|
|
425
453
|
label: option.label,
|
|
426
454
|
value: option.value,
|
|
427
455
|
isSelected: selectedIndex === index,
|
|
@@ -430,6 +458,9 @@ function QuickActionsSection({
|
|
|
430
458
|
}), /*#__PURE__*/_jsxs(View, {
|
|
431
459
|
style: styles.filterActionButtons,
|
|
432
460
|
children: [/*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
461
|
+
testID: "buoy-highlight-quick-include",
|
|
462
|
+
accessibilityRole: "button",
|
|
463
|
+
accessibilityLabel: "Only show this",
|
|
433
464
|
style: [styles.filterActionButton, styles.filterActionButtonInclude, !selectedOption && styles.filterActionButtonDisabled],
|
|
434
465
|
onPress: handleInclude,
|
|
435
466
|
disabled: !selectedOption,
|
|
@@ -444,6 +475,9 @@ function QuickActionsSection({
|
|
|
444
475
|
children: "Only Show This"
|
|
445
476
|
})]
|
|
446
477
|
}), /*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
478
|
+
testID: "buoy-highlight-quick-exclude",
|
|
479
|
+
accessibilityRole: "button",
|
|
480
|
+
accessibilityLabel: "Hide this",
|
|
447
481
|
style: [styles.filterActionButton, styles.filterActionButtonExclude, !selectedOption && styles.filterActionButtonDisabled],
|
|
448
482
|
onPress: handleExclude,
|
|
449
483
|
disabled: !selectedOption,
|
|
@@ -466,12 +500,16 @@ function QuickActionsSection({
|
|
|
466
500
|
* FilterOptionCard - A selectable filter option card
|
|
467
501
|
*/
|
|
468
502
|
function FilterOptionCard({
|
|
503
|
+
testID,
|
|
469
504
|
label,
|
|
470
505
|
value,
|
|
471
506
|
isSelected,
|
|
472
507
|
onSelect
|
|
473
508
|
}) {
|
|
474
509
|
return /*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
510
|
+
testID: testID,
|
|
511
|
+
accessibilityRole: "button",
|
|
512
|
+
accessibilityLabel: `${label}, ${value}`,
|
|
475
513
|
style: [styles.filterOptionCard, isSelected && styles.filterOptionCardSelected],
|
|
476
514
|
onPress: onSelect,
|
|
477
515
|
activeOpacity: 0.7,
|
|
@@ -479,6 +517,7 @@ function FilterOptionCard({
|
|
|
479
517
|
style: [styles.filterOptionLabel, isSelected && styles.filterOptionLabelSelected],
|
|
480
518
|
children: label
|
|
481
519
|
}), /*#__PURE__*/_jsx(Text, {
|
|
520
|
+
testID: testID ? `${testID}-value` : undefined,
|
|
482
521
|
style: [styles.filterOptionValue, isSelected && styles.filterOptionValueSelected],
|
|
483
522
|
numberOfLines: 1,
|
|
484
523
|
children: value
|
|
@@ -15,15 +15,22 @@ import { TreeDiffViewer } from "@buoy-gg/shared-ui/dataViewer";
|
|
|
15
15
|
import { EnhancedCauseDisplay, CAUSE_CONFIG } from "./RenderCauseBadge";
|
|
16
16
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
18
|
+
* `HH:MM:SS.mmm` — the same shape Redux, Zustand and Jotai print for the same
|
|
19
|
+
* job, and for the same reason: the milliseconds are the point.
|
|
20
|
+
*
|
|
21
|
+
* Built by hand rather than from `toLocaleTimeString`, which appends the day
|
|
22
|
+
* period on a 12-hour locale — so concatenating the milliseconds to the end of
|
|
23
|
+
* it produced "8:21:44 AM.351", with the fraction attached to the wrong part
|
|
24
|
+
* of the time. It also made the string depend on the hour of day, which is a
|
|
25
|
+
* fine way to have a test that only passes after 10am.
|
|
19
26
|
*/
|
|
20
27
|
function formatTimeWithMs(timestamp) {
|
|
21
28
|
const date = new Date(timestamp);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
const h = date.getHours().toString().padStart(2, "0");
|
|
30
|
+
const m = date.getMinutes().toString().padStart(2, "0");
|
|
31
|
+
const s = date.getSeconds().toString().padStart(2, "0");
|
|
32
|
+
const ms = date.getMilliseconds().toString().padStart(3, "0");
|
|
33
|
+
return `${h}:${m}:${s}.${ms}`;
|
|
27
34
|
}
|
|
28
35
|
|
|
29
36
|
/**
|
|
@@ -83,14 +90,17 @@ export function RenderHistoryViewer({
|
|
|
83
90
|
// If no history, show empty state
|
|
84
91
|
if (totalEvents === 0) {
|
|
85
92
|
return /*#__PURE__*/_jsxs(View, {
|
|
93
|
+
testID: "buoy-highlight-history-empty",
|
|
86
94
|
style: styles.emptyContainer,
|
|
87
95
|
children: [/*#__PURE__*/_jsx(Clock, {
|
|
88
96
|
size: 32,
|
|
89
97
|
color: night.color.textTertiary
|
|
90
98
|
}), /*#__PURE__*/_jsx(Text, {
|
|
99
|
+
testID: "buoy-highlight-history-empty-title",
|
|
91
100
|
style: styles.emptyTitle,
|
|
92
101
|
children: "No Render History"
|
|
93
102
|
}), /*#__PURE__*/_jsx(Text, {
|
|
103
|
+
testID: "buoy-highlight-history-empty-text",
|
|
94
104
|
style: styles.emptyText,
|
|
95
105
|
children: "Enable render history tracking in settings to see render events here."
|
|
96
106
|
})]
|
|
@@ -102,11 +112,13 @@ export function RenderHistoryViewer({
|
|
|
102
112
|
paddingBottom: !disableInternalFooter && totalEvents > 1 ? 80 : 0
|
|
103
113
|
}],
|
|
104
114
|
children: [lockedEventCount > 0 && /*#__PURE__*/_jsxs(View, {
|
|
115
|
+
testID: "buoy-highlight-history-locked",
|
|
105
116
|
style: styles.lockedBanner,
|
|
106
117
|
children: [/*#__PURE__*/_jsx(Lock, {
|
|
107
118
|
size: 14,
|
|
108
119
|
color: night.color.warning
|
|
109
120
|
}), /*#__PURE__*/_jsxs(Text, {
|
|
121
|
+
testID: "buoy-highlight-history-locked-text",
|
|
110
122
|
style: styles.lockedBannerText,
|
|
111
123
|
children: [lockedEventCount, " older ", lockedEventCount === 1 ? 'render' : 'renders', " locked"]
|
|
112
124
|
}), /*#__PURE__*/_jsx(Text, {
|
|
@@ -116,6 +128,9 @@ export function RenderHistoryViewer({
|
|
|
116
128
|
}), /*#__PURE__*/_jsxs(View, {
|
|
117
129
|
style: styles.viewToggleContainer,
|
|
118
130
|
children: [/*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
131
|
+
testID: "buoy-highlight-history-mode-current",
|
|
132
|
+
accessibilityRole: "button",
|
|
133
|
+
accessibilityLabel: "Current state",
|
|
119
134
|
style: [styles.viewToggleCard, activeView === "current" && styles.viewToggleCardActive],
|
|
120
135
|
onPress: () => setActiveView("current"),
|
|
121
136
|
activeOpacity: 0.8,
|
|
@@ -135,6 +150,8 @@ export function RenderHistoryViewer({
|
|
|
135
150
|
children: ["View render #", currentEvent?.renderNumber ?? 0, " details"]
|
|
136
151
|
})]
|
|
137
152
|
}), /*#__PURE__*/_jsxs(View, {
|
|
153
|
+
testID: "buoy-highlight-history-mode-diff",
|
|
154
|
+
accessibilityLabel: "Diff view, coming soon",
|
|
138
155
|
style: [styles.viewToggleCard, styles.viewToggleCardDisabled],
|
|
139
156
|
children: [/*#__PURE__*/_jsxs(View, {
|
|
140
157
|
style: styles.viewToggleContent,
|
|
@@ -159,6 +176,7 @@ export function RenderHistoryViewer({
|
|
|
159
176
|
})]
|
|
160
177
|
})]
|
|
161
178
|
}), /*#__PURE__*/_jsx(ScrollView, {
|
|
179
|
+
testID: "buoy-highlight-history-scroll",
|
|
162
180
|
style: styles.contentScroll,
|
|
163
181
|
contentContainerStyle: styles.contentContainer,
|
|
164
182
|
showsVerticalScrollIndicator: false,
|
|
@@ -191,6 +209,7 @@ function CurrentStateView({
|
|
|
191
209
|
}) {
|
|
192
210
|
if (!event) {
|
|
193
211
|
return /*#__PURE__*/_jsx(View, {
|
|
212
|
+
testID: "buoy-highlight-history-no-event",
|
|
194
213
|
style: styles.noEventContainer,
|
|
195
214
|
children: /*#__PURE__*/_jsx(Text, {
|
|
196
215
|
style: styles.noEventText,
|
|
@@ -206,9 +225,11 @@ function CurrentStateView({
|
|
|
206
225
|
children: [/*#__PURE__*/_jsxs(View, {
|
|
207
226
|
style: styles.eventHeaderLeft,
|
|
208
227
|
children: [/*#__PURE__*/_jsxs(Text, {
|
|
228
|
+
testID: "buoy-highlight-history-event-title",
|
|
209
229
|
style: styles.eventTitle,
|
|
210
230
|
children: ["Render #", event.renderNumber]
|
|
211
231
|
}), /*#__PURE__*/_jsx(Text, {
|
|
232
|
+
testID: "buoy-highlight-history-event-time",
|
|
212
233
|
style: styles.eventTime,
|
|
213
234
|
children: formatTimeWithMs(event.timestamp)
|
|
214
235
|
})]
|
|
@@ -221,6 +242,7 @@ function CurrentStateView({
|
|
|
221
242
|
backgroundColor: render.color
|
|
222
243
|
}]
|
|
223
244
|
}), /*#__PURE__*/_jsx(Text, {
|
|
245
|
+
testID: "buoy-highlight-history-event-cause",
|
|
224
246
|
style: [styles.eventBadgeText, {
|
|
225
247
|
color: render.color
|
|
226
248
|
}],
|
|
@@ -261,6 +283,7 @@ function CurrentStateView({
|
|
|
261
283
|
showsHorizontalScrollIndicator: false,
|
|
262
284
|
style: styles.propsScrollView,
|
|
263
285
|
children: /*#__PURE__*/_jsx(Text, {
|
|
286
|
+
testID: "buoy-highlight-history-props",
|
|
264
287
|
style: styles.propsJson,
|
|
265
288
|
children: JSON.stringify(event.capturedProps, null, 2)
|
|
266
289
|
})
|
|
@@ -12,6 +12,7 @@ import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
|
|
|
12
12
|
import { ChevronRight, night, useRelativeTime } from "@buoy-gg/shared-ui";
|
|
13
13
|
import { IdentifierBadge } from "./IdentifierBadge";
|
|
14
14
|
import { RenderCauseBadge } from "./RenderCauseBadge";
|
|
15
|
+
import { renderRowTestID } from "../utils/testIDs";
|
|
15
16
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
16
17
|
function RenderListItemInner({
|
|
17
18
|
render,
|
|
@@ -54,7 +55,15 @@ function RenderListItemInner({
|
|
|
54
55
|
|
|
55
56
|
// Format time since last render (live-updating)
|
|
56
57
|
const timeSinceRender = useRelativeTime(render.lastRenderTime);
|
|
58
|
+
|
|
59
|
+
// The row is addressed by the identifier it SHOWS, never by nativeTag — see
|
|
60
|
+
// utils/testIDs.ts for why a tag can't be a handle. The label spells the row
|
|
61
|
+
// out for assistive tech, which otherwise gets a coloured bar and a count.
|
|
62
|
+
const rowTestID = renderRowTestID(identifier.value);
|
|
57
63
|
return /*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
64
|
+
testID: rowTestID,
|
|
65
|
+
accessibilityRole: "button",
|
|
66
|
+
accessibilityLabel: `${render.displayName}, ${identifier.type} ${identifier.value}, ${render.renderCount} renders`,
|
|
58
67
|
style: styles.container,
|
|
59
68
|
onPress: () => onPress(render),
|
|
60
69
|
activeOpacity: 0.7,
|
|
@@ -69,6 +78,7 @@ function RenderListItemInner({
|
|
|
69
78
|
children: [/*#__PURE__*/_jsxs(View, {
|
|
70
79
|
style: styles.viewTypeContainer,
|
|
71
80
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
81
|
+
testID: `${rowTestID}-name`,
|
|
72
82
|
style: styles.viewType,
|
|
73
83
|
numberOfLines: 1,
|
|
74
84
|
children: render.displayName
|
|
@@ -78,6 +88,7 @@ function RenderListItemInner({
|
|
|
78
88
|
compact: true,
|
|
79
89
|
shortLabel: true
|
|
80
90
|
}) : render.displayName !== render.viewType ? /*#__PURE__*/_jsx(Text, {
|
|
91
|
+
testID: `${rowTestID}-type`,
|
|
81
92
|
style: styles.nativeType,
|
|
82
93
|
numberOfLines: 1,
|
|
83
94
|
children: render.viewType
|
|
@@ -87,6 +98,7 @@ function RenderListItemInner({
|
|
|
87
98
|
backgroundColor: render.color + "30"
|
|
88
99
|
}],
|
|
89
100
|
children: /*#__PURE__*/_jsxs(Text, {
|
|
101
|
+
testID: `${rowTestID}-count`,
|
|
90
102
|
style: [styles.renderCount, {
|
|
91
103
|
color: render.color
|
|
92
104
|
}],
|
|
@@ -96,6 +108,7 @@ function RenderListItemInner({
|
|
|
96
108
|
}), render.lastRenderCause && /*#__PURE__*/_jsx(View, {
|
|
97
109
|
style: styles.causeRow,
|
|
98
110
|
children: /*#__PURE__*/_jsx(RenderCauseBadge, {
|
|
111
|
+
testID: `${rowTestID}-cause`,
|
|
99
112
|
cause: render.lastRenderCause,
|
|
100
113
|
compact: true,
|
|
101
114
|
showKeys: true,
|
|
@@ -106,12 +119,14 @@ function RenderListItemInner({
|
|
|
106
119
|
children: [/*#__PURE__*/_jsx(View, {
|
|
107
120
|
style: styles.identifierContainer,
|
|
108
121
|
children: /*#__PURE__*/_jsx(IdentifierBadge, {
|
|
122
|
+
testID: `${rowTestID}-identifier`,
|
|
109
123
|
type: identifier.type,
|
|
110
124
|
value: identifier.value,
|
|
111
125
|
compact: true,
|
|
112
126
|
shortLabel: true
|
|
113
127
|
})
|
|
114
128
|
}), /*#__PURE__*/_jsx(Text, {
|
|
129
|
+
testID: `${rowTestID}-time`,
|
|
115
130
|
style: styles.timing,
|
|
116
131
|
children: timeSinceRender
|
|
117
132
|
})]
|
|
@@ -196,6 +196,9 @@ export function RendersCopySettingsView({
|
|
|
196
196
|
return /*#__PURE__*/_jsxs(View, {
|
|
197
197
|
style: styles.collapsedPreview,
|
|
198
198
|
children: [/*#__PURE__*/_jsx(TouchableOpacity, {
|
|
199
|
+
testID: "buoy-highlight-copy-preview-show",
|
|
200
|
+
accessibilityRole: "button",
|
|
201
|
+
accessibilityLabel: "Show preview",
|
|
199
202
|
style: styles.expandButton,
|
|
200
203
|
onPress: () => setIsPreviewExpanded(true),
|
|
201
204
|
children: /*#__PURE__*/_jsxs(View, {
|
|
@@ -209,6 +212,7 @@ export function RendersCopySettingsView({
|
|
|
209
212
|
style: styles.expandButtonTitle,
|
|
210
213
|
children: "Show Preview"
|
|
211
214
|
}), /*#__PURE__*/_jsxs(Text, {
|
|
215
|
+
testID: "buoy-highlight-copy-preview-summary",
|
|
212
216
|
style: styles.expandButtonSubtitle,
|
|
213
217
|
children: [totalComponents, " component", totalComponents !== 1 ? "s" : "", " \xB7 ", totalRenders, " renders \xB7 ~", formatBytes(estimatedSize), !hasLiveData ? " (mock data)" : ""]
|
|
214
218
|
})]
|
|
@@ -218,6 +222,7 @@ export function RendersCopySettingsView({
|
|
|
218
222
|
})]
|
|
219
223
|
})
|
|
220
224
|
}), sizeWarningLevel !== "none" && /*#__PURE__*/_jsxs(View, {
|
|
225
|
+
testID: "buoy-highlight-copy-size-warning",
|
|
221
226
|
style: [styles.sizeWarning, sizeWarningLevel === "danger" && styles.sizeWarningDanger],
|
|
222
227
|
children: [/*#__PURE__*/_jsx(AlertTriangle, {
|
|
223
228
|
size: 12,
|
|
@@ -234,6 +239,9 @@ export function RendersCopySettingsView({
|
|
|
234
239
|
const exportText = generateCopyText();
|
|
235
240
|
return /*#__PURE__*/_jsxs(View, {
|
|
236
241
|
children: [/*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
242
|
+
testID: "buoy-highlight-copy-preview-hide",
|
|
243
|
+
accessibilityRole: "button",
|
|
244
|
+
accessibilityLabel: "Hide preview",
|
|
237
245
|
style: styles.collapseButton,
|
|
238
246
|
onPress: () => setIsPreviewExpanded(false),
|
|
239
247
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
@@ -244,9 +252,11 @@ export function RendersCopySettingsView({
|
|
|
244
252
|
color: night.color.textSecondary
|
|
245
253
|
})]
|
|
246
254
|
}), /*#__PURE__*/_jsx(ScrollView, {
|
|
255
|
+
testID: "buoy-highlight-copy-preview-scroll",
|
|
247
256
|
style: styles.previewScroll,
|
|
248
257
|
nestedScrollEnabled: true,
|
|
249
258
|
children: /*#__PURE__*/_jsx(Text, {
|
|
259
|
+
testID: "buoy-highlight-copy-preview-text",
|
|
250
260
|
style: styles.previewText,
|
|
251
261
|
selectable: true,
|
|
252
262
|
children: exportText
|
|
@@ -261,6 +271,7 @@ export function RendersCopySettingsView({
|
|
|
261
271
|
const statusLabel = hasLiveData ? `${totalComponents} components` : "Mock data (no renders captured)";
|
|
262
272
|
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
263
273
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
274
|
+
testID: "buoy-highlight-copy-status",
|
|
264
275
|
style: styles.statusLabel,
|
|
265
276
|
children: statusLabel
|
|
266
277
|
}), /*#__PURE__*/_jsx(ToolbarCopyButton, {
|
|
@@ -33,11 +33,14 @@ function StatsDisplayInner() {
|
|
|
33
33
|
}, []);
|
|
34
34
|
return /*#__PURE__*/_jsxs(View, {
|
|
35
35
|
nativeID: "__rn_buoy__stats-row",
|
|
36
|
+
testID: "buoy-highlight-stats",
|
|
37
|
+
accessibilityLabel: `${stats.totalComponents} components tracked`,
|
|
36
38
|
style: styles.headerChip,
|
|
37
39
|
children: [/*#__PURE__*/_jsx(Activity, {
|
|
38
40
|
size: 12,
|
|
39
41
|
color: night.color.accent
|
|
40
42
|
}), /*#__PURE__*/_jsx(Text, {
|
|
43
|
+
testID: "buoy-highlight-stats-value",
|
|
41
44
|
style: [styles.headerChipValue, {
|
|
42
45
|
color: night.color.accent
|
|
43
46
|
}],
|
|
@@ -19,6 +19,10 @@
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
import { isDevToolsComponentName, isRenderLoopUnsafeName } from "./devtoolsComponentNames";
|
|
22
|
+
// One implementation, shared with the overlay's RenderCauseDetector — the two
|
|
23
|
+
// classifiers are separate on purpose, but this question is not. See the file
|
|
24
|
+
// for why the obvious identity check is wrong.
|
|
25
|
+
import { ownStateChanged } from "./ownStateChanged";
|
|
22
26
|
|
|
23
27
|
// React work tags for components that render user code.
|
|
24
28
|
const FunctionComponent = 0;
|
|
@@ -206,7 +210,7 @@ function detectCause(fiber, wantKeys) {
|
|
|
206
210
|
}
|
|
207
211
|
|
|
208
212
|
// No prop change of substance. Own state/hooks next.
|
|
209
|
-
if (prev
|
|
213
|
+
if (ownStateChanged(prev, fiber)) return {
|
|
210
214
|
cause: "hooks"
|
|
211
215
|
};
|
|
212
216
|
return {
|
|
@@ -30,6 +30,8 @@
|
|
|
30
30
|
import { installProfilerInterceptor, uninstallProfilerInterceptor, setComparisonCallback } from "./ProfilerInterceptor";
|
|
31
31
|
import { findNodeHandle, UIManager, Dimensions, PixelRatio } from "react-native";
|
|
32
32
|
import { RenderTracker } from "./RenderTracker";
|
|
33
|
+
import { describeScreen } from "./screenElements";
|
|
34
|
+
import { scoreTapMatch } from "./tapMatch";
|
|
33
35
|
import { PerformanceLogger, markEventReceived } from "./PerformanceLogger";
|
|
34
36
|
import { detectRenderCause, clearRenderCauseState } from "./RenderCauseDetector";
|
|
35
37
|
import { notifySubscriberCountChange } from "@buoy-gg/shared-ui";
|
|
@@ -1165,10 +1167,60 @@ async function locateComponent(params) {
|
|
|
1165
1167
|
const margin = typeof params.margin === "number" ? params.margin : 12;
|
|
1166
1168
|
const renders = RenderTracker.getRenders();
|
|
1167
1169
|
if (renders.length === 0) {
|
|
1170
|
+
const described = await describeScreen();
|
|
1171
|
+
const q = (params.query ?? "").trim().toLowerCase();
|
|
1172
|
+
let best;
|
|
1173
|
+
for (const el of described.elements) {
|
|
1174
|
+
if (params.nativeTag != null && el.nativeTag === params.nativeTag) {
|
|
1175
|
+
best = {
|
|
1176
|
+
el,
|
|
1177
|
+
score: 1000
|
|
1178
|
+
};
|
|
1179
|
+
break;
|
|
1180
|
+
}
|
|
1181
|
+
const score = scoreTapMatch({
|
|
1182
|
+
nativeTag: el.nativeTag,
|
|
1183
|
+
testID: el.testID,
|
|
1184
|
+
label: el.label,
|
|
1185
|
+
text: el.text,
|
|
1186
|
+
name: el.name,
|
|
1187
|
+
tap: el.tap
|
|
1188
|
+
}, {
|
|
1189
|
+
query: q || undefined,
|
|
1190
|
+
nativeTag: params.nativeTag
|
|
1191
|
+
});
|
|
1192
|
+
if (score <= 0) continue;
|
|
1193
|
+
if (!best || score > best.score) best = {
|
|
1194
|
+
el,
|
|
1195
|
+
score
|
|
1196
|
+
};
|
|
1197
|
+
}
|
|
1198
|
+
if (!best?.el.frame) {
|
|
1199
|
+
return {
|
|
1200
|
+
matched: false,
|
|
1201
|
+
reason: "no-match",
|
|
1202
|
+
candidates: []
|
|
1203
|
+
};
|
|
1204
|
+
}
|
|
1205
|
+
const win = described.screen;
|
|
1206
|
+
const f = best.el.frame;
|
|
1168
1207
|
return {
|
|
1169
|
-
matched:
|
|
1170
|
-
|
|
1171
|
-
|
|
1208
|
+
matched: true,
|
|
1209
|
+
live: true,
|
|
1210
|
+
rect: {
|
|
1211
|
+
x: f.x * win.width,
|
|
1212
|
+
y: f.y * win.height,
|
|
1213
|
+
width: f.width * win.width,
|
|
1214
|
+
height: f.height * win.height
|
|
1215
|
+
},
|
|
1216
|
+
scale: PixelRatio.get(),
|
|
1217
|
+
screen: {
|
|
1218
|
+
width: win.width,
|
|
1219
|
+
height: win.height
|
|
1220
|
+
},
|
|
1221
|
+
nativeTag: best.el.nativeTag ?? undefined,
|
|
1222
|
+
componentName: best.el.name,
|
|
1223
|
+
testID: best.el.testID
|
|
1172
1224
|
};
|
|
1173
1225
|
}
|
|
1174
1226
|
|
|
@@ -1570,6 +1622,16 @@ function disable() {
|
|
|
1570
1622
|
devToolsNodeCache.clear(); // Clear detection cache
|
|
1571
1623
|
clearRenderCauseState(); // Clear render cause state to prevent memory leaks
|
|
1572
1624
|
|
|
1625
|
+
// Freeze is a view state on a LIVE overlay, and the overlay is going away:
|
|
1626
|
+
// the boxes it was holding open were just cleared with the tags above. Left
|
|
1627
|
+
// latched it outlived the thing it froze — switch tracking off and back on
|
|
1628
|
+
// and the button still read "Unfreeze frame" on a tool with nothing frozen,
|
|
1629
|
+
// while new highlights (correctly) refused to fade.
|
|
1630
|
+
if (isFrozen) {
|
|
1631
|
+
isFrozen = false;
|
|
1632
|
+
notifyFreezeListeners();
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1573
1635
|
// Only unsubscribe if background tracking doesn't need it
|
|
1574
1636
|
if (!backgroundTrackingEnabled) {
|
|
1575
1637
|
unsubscribeFromTraceUpdates();
|
|
@@ -26,6 +26,11 @@
|
|
|
26
26
|
|
|
27
27
|
"use strict";
|
|
28
28
|
|
|
29
|
+
// One implementation of "did this component's own state actually change?",
|
|
30
|
+
// shared with CommitProfiler. The two classifiers are separate on purpose;
|
|
31
|
+
// this question is not, and both of them got it wrong the same way.
|
|
32
|
+
import { hookStateChanged } from "./ownStateChanged";
|
|
33
|
+
|
|
29
34
|
// ============================================================================
|
|
30
35
|
// TYPE DEFINITIONS
|
|
31
36
|
// Based on React Native source: packages/react-native/Libraries/Renderer/
|
|
@@ -650,9 +655,16 @@ function detectComponentCause(componentFiber) {
|
|
|
650
655
|
|
|
651
656
|
// Check if state changed (for hooks, memoizedState is a linked list)
|
|
652
657
|
// This means useState/useReducer triggered a re-render
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
658
|
+
// NOT `prevMemoizedState !== currentFiber.memoizedState`, which is what this
|
|
659
|
+
// used to be — see utils/ownStateChanged.ts for why that is wrong and what
|
|
660
|
+
// it cost. Shared with `CommitProfiler`, which reached the same wrong line
|
|
661
|
+
// independently; the two classifiers stay separate, this one question does
|
|
662
|
+
// not.
|
|
663
|
+
if (hookStateChanged(prevMemoizedState, currentFiber.memoizedState, {
|
|
664
|
+
isClassComponent: currentFiber.tag === 1
|
|
665
|
+
})) {
|
|
666
|
+
// Phase 3: the actual before/after values, for the UI. Only needed once
|
|
667
|
+
// the cause is settled, and only the overlay displays them.
|
|
656
668
|
const hookChanges = compareHookStates(prevExtractedHooks, currentHooks);
|
|
657
669
|
return {
|
|
658
670
|
cause: "state",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import { getComponentDisplayName } from "./ViewTypeMapper";
|
|
12
12
|
import { PerformanceLogger } from "./PerformanceLogger";
|
|
13
|
+
import { isNamedComposite } from "./namedComposite";
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Debug logging levels for render cause detection.
|
|
@@ -69,7 +70,8 @@ class RenderTrackerSingleton {
|
|
|
69
70
|
// Debug settings
|
|
70
71
|
debugLogLevel: "off",
|
|
71
72
|
// Dev tools visibility - exclude by default
|
|
72
|
-
excludeDevTools: true
|
|
73
|
+
excludeDevTools: true,
|
|
74
|
+
showHostViews: false
|
|
73
75
|
};
|
|
74
76
|
|
|
75
77
|
// Batch mode: defer notifyListeners until endBatch is called
|
|
@@ -418,6 +420,9 @@ class RenderTrackerSingleton {
|
|
|
418
420
|
*/
|
|
419
421
|
getFilteredRenders(searchText = "") {
|
|
420
422
|
let renders = this.getRenders();
|
|
423
|
+
if (!this.settings.showHostViews) {
|
|
424
|
+
renders = renders.filter(isNamedComposite);
|
|
425
|
+
}
|
|
421
426
|
|
|
422
427
|
// Apply search filter
|
|
423
428
|
if (searchText.trim()) {
|