@buoy-gg/events 2.1.2 → 2.1.3
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/components/EventsCopySettingsView.js +39 -8
- package/lib/commonjs/components/UnifiedEventDetail.js +32 -1
- package/lib/commonjs/components/UnifiedEventFilters.js +50 -21
- package/lib/commonjs/components/UnifiedEventItem.js +6 -1
- package/lib/commonjs/hooks/useUnifiedEvents.js +137 -28
- package/lib/commonjs/index.js +6 -0
- package/lib/commonjs/stores/unifiedEventStore.js +61 -16
- package/lib/commonjs/types/copySettings.js +29 -0
- package/lib/commonjs/utils/autoDiscoverEventSources.js +261 -39
- package/lib/commonjs/utils/badgeSelectionStorage.js +32 -0
- package/lib/commonjs/utils/eventExportFormatter.js +778 -1
- package/lib/module/components/EventsCopySettingsView.js +40 -9
- package/lib/module/components/UnifiedEventDetail.js +32 -1
- package/lib/module/components/UnifiedEventFilters.js +50 -21
- package/lib/module/components/UnifiedEventItem.js +6 -1
- package/lib/module/hooks/useUnifiedEvents.js +140 -31
- package/lib/module/index.js +4 -1
- package/lib/module/stores/unifiedEventStore.js +58 -16
- package/lib/module/types/copySettings.js +29 -0
- package/lib/module/utils/autoDiscoverEventSources.js +260 -39
- package/lib/module/utils/badgeSelectionStorage.js +30 -0
- package/lib/module/utils/eventExportFormatter.js +777 -1
- package/lib/typescript/components/UnifiedEventFilters.d.ts +3 -0
- package/lib/typescript/hooks/useUnifiedEvents.d.ts +2 -0
- package/lib/typescript/index.d.ts +1 -1
- package/lib/typescript/stores/unifiedEventStore.d.ts +18 -2
- package/lib/typescript/types/copySettings.d.ts +25 -1
- package/lib/typescript/types/index.d.ts +3 -1
- package/lib/typescript/utils/autoDiscoverEventSources.d.ts +17 -0
- package/lib/typescript/utils/badgeSelectionStorage.d.ts +9 -0
- package/lib/typescript/utils/eventExportFormatter.d.ts +4 -0
- package/package.json +3 -3
- package/src/components/EventsCopySettingsView.tsx +41 -5
- package/src/components/UnifiedEventDetail.tsx +28 -0
- package/src/components/UnifiedEventFilters.tsx +88 -21
- package/src/components/UnifiedEventItem.tsx +5 -0
- package/src/hooks/useUnifiedEvents.ts +153 -25
- package/src/index.tsx +4 -0
- package/src/stores/unifiedEventStore.ts +58 -12
- package/src/types/copySettings.ts +31 -1
- package/src/types/index.ts +4 -1
- package/src/utils/autoDiscoverEventSources.ts +268 -44
- package/src/utils/badgeSelectionStorage.ts +30 -0
- package/src/utils/eventExportFormatter.ts +797 -0
|
@@ -267,14 +267,19 @@ function EventsCopySettingsView({
|
|
|
267
267
|
data: JSON.parse(exportText),
|
|
268
268
|
title: "",
|
|
269
269
|
showTypeFilter: false
|
|
270
|
-
}) : /*#__PURE__*/(0, _jsxRuntime.
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
270
|
+
}) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
271
|
+
children: [settings.format === "mermaid" && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
272
|
+
style: styles.mermaidHint,
|
|
273
|
+
children: "\uD83D\uDCA1 Paste into mermaid.live to visualize"
|
|
274
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
|
|
275
|
+
style: styles.previewScroll,
|
|
276
|
+
nestedScrollEnabled: true,
|
|
277
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
278
|
+
style: styles.previewText,
|
|
279
|
+
selectable: isPro,
|
|
280
|
+
children: exportText
|
|
281
|
+
})
|
|
282
|
+
})]
|
|
278
283
|
})]
|
|
279
284
|
});
|
|
280
285
|
}, [isPreviewExpanded, previewEvents, settings, estimatedSize, sizeWarningLevel, hasLiveData, generateCopyText, isPro]);
|
|
@@ -341,6 +346,14 @@ function EventsCopySettingsView({
|
|
|
341
346
|
value: "minimal",
|
|
342
347
|
isActive: activePreset === "minimal",
|
|
343
348
|
description: _copySettings.PRESET_METADATA.minimal.description
|
|
349
|
+
}, {
|
|
350
|
+
id: "preset::mermaid",
|
|
351
|
+
label: _copySettings.PRESET_METADATA.mermaid.label,
|
|
352
|
+
icon: _sharedUi.GitBranch,
|
|
353
|
+
color: _copySettings.PRESET_METADATA.mermaid.color,
|
|
354
|
+
value: "mermaid",
|
|
355
|
+
isActive: activePreset === "mermaid",
|
|
356
|
+
description: _copySettings.PRESET_METADATA.mermaid.description
|
|
344
357
|
}, {
|
|
345
358
|
id: "preset::custom",
|
|
346
359
|
label: "Custom",
|
|
@@ -424,6 +437,14 @@ function EventsCopySettingsView({
|
|
|
424
437
|
color: _sharedUi.macOSColors.text.secondary,
|
|
425
438
|
value: "plaintext",
|
|
426
439
|
isActive: settings.format === "plaintext"
|
|
440
|
+
}, {
|
|
441
|
+
id: "format::mermaid",
|
|
442
|
+
label: "Diagram",
|
|
443
|
+
icon: _sharedUi.GitBranch,
|
|
444
|
+
color: "#A855F7",
|
|
445
|
+
value: "mermaid",
|
|
446
|
+
isActive: settings.format === "mermaid",
|
|
447
|
+
description: "Mermaid sequence diagram"
|
|
427
448
|
}]
|
|
428
449
|
},
|
|
429
450
|
// Timestamp Section
|
|
@@ -625,6 +646,16 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
625
646
|
color: _sharedUi.macOSColors.text.primary,
|
|
626
647
|
lineHeight: 18
|
|
627
648
|
},
|
|
649
|
+
mermaidHint: {
|
|
650
|
+
fontSize: 11,
|
|
651
|
+
color: _sharedUi.macOSColors.text.secondary,
|
|
652
|
+
marginBottom: 8,
|
|
653
|
+
paddingHorizontal: 8,
|
|
654
|
+
paddingVertical: 6,
|
|
655
|
+
backgroundColor: "#A855F7" + "15",
|
|
656
|
+
borderRadius: 6,
|
|
657
|
+
overflow: "hidden"
|
|
658
|
+
},
|
|
628
659
|
statusLabel: {
|
|
629
660
|
fontSize: 11,
|
|
630
661
|
fontWeight: "600",
|
|
@@ -26,7 +26,8 @@ function tryLoadOptionalDetailComponents() {
|
|
|
26
26
|
const components = {
|
|
27
27
|
StorageEventDetailContent: null,
|
|
28
28
|
ReduxActionDetailContent: null,
|
|
29
|
-
NetworkEventDetailView: null
|
|
29
|
+
NetworkEventDetailView: null,
|
|
30
|
+
RenderDetailView: null
|
|
30
31
|
};
|
|
31
32
|
|
|
32
33
|
// Try to load storage detail component
|
|
@@ -55,6 +56,15 @@ function tryLoadOptionalDetailComponents() {
|
|
|
55
56
|
} catch {
|
|
56
57
|
// Optional dependency not installed
|
|
57
58
|
}
|
|
59
|
+
|
|
60
|
+
// Try to load render detail component
|
|
61
|
+
try {
|
|
62
|
+
// @ts-ignore - Dynamic import that may not exist
|
|
63
|
+
const highlightUpdates = require("@buoy-gg/highlight-updates");
|
|
64
|
+
components.RenderDetailView = highlightUpdates.RenderDetailView;
|
|
65
|
+
} catch {
|
|
66
|
+
// Optional dependency not installed
|
|
67
|
+
}
|
|
58
68
|
return components;
|
|
59
69
|
}
|
|
60
70
|
|
|
@@ -100,6 +110,10 @@ const SOURCE_CONFIG = {
|
|
|
100
110
|
route: {
|
|
101
111
|
label: "Route",
|
|
102
112
|
color: "#06B6D4"
|
|
113
|
+
},
|
|
114
|
+
render: {
|
|
115
|
+
label: "Render",
|
|
116
|
+
color: "#F472B6"
|
|
103
117
|
}
|
|
104
118
|
};
|
|
105
119
|
|
|
@@ -215,6 +229,23 @@ const UnifiedEventDetail = exports.UnifiedEventDetail = /*#__PURE__*/(0, _react.
|
|
|
215
229
|
});
|
|
216
230
|
}
|
|
217
231
|
|
|
232
|
+
// For render events, use the RenderDetailView if available
|
|
233
|
+
if (event.source === "render" && optionalComponents.RenderDetailView) {
|
|
234
|
+
const {
|
|
235
|
+
RenderDetailView
|
|
236
|
+
} = optionalComponents;
|
|
237
|
+
const renderData = event.originalEvent;
|
|
238
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
239
|
+
style: styles.container,
|
|
240
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
|
|
241
|
+
style: styles.content,
|
|
242
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(RenderDetailView, {
|
|
243
|
+
render: renderData.render
|
|
244
|
+
})
|
|
245
|
+
})
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
218
249
|
// Route events expand in-place in the list, so they shouldn't reach this detail view
|
|
219
250
|
// If they do somehow, fall through to the generic view
|
|
220
251
|
|
|
@@ -14,6 +14,9 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
14
14
|
* Filter bar showing toggleable badges for each available event source.
|
|
15
15
|
* Badges are sorted: enabled first, disabled last.
|
|
16
16
|
* Toggling a badge enables/disables event listening for that source.
|
|
17
|
+
*
|
|
18
|
+
* Badge layout (inspired by React Query DevTools):
|
|
19
|
+
* [subscriber_count] • Label [event_count]
|
|
17
20
|
*/
|
|
18
21
|
|
|
19
22
|
const UnifiedEventFilters = exports.UnifiedEventFilters = /*#__PURE__*/(0, _react.memo)(function UnifiedEventFilters({
|
|
@@ -33,27 +36,45 @@ const UnifiedEventFilters = exports.UnifiedEventFilters = /*#__PURE__*/(0, _reac
|
|
|
33
36
|
contentContainerStyle: styles.badgesRow,
|
|
34
37
|
children: availableSources.map(source => {
|
|
35
38
|
const isEnabled = source.enabled !== false;
|
|
39
|
+
const subscriberCount = source.subscriberCount;
|
|
40
|
+
const hasSubscriberTracking = subscriberCount !== undefined;
|
|
41
|
+
const eventCount = source.count || 0;
|
|
36
42
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
|
|
37
43
|
style: [styles.badge, isEnabled ? {
|
|
38
|
-
backgroundColor:
|
|
39
|
-
borderColor: source.color + "
|
|
44
|
+
backgroundColor: _sharedUi.buoyColors.card,
|
|
45
|
+
borderColor: source.color + "50"
|
|
40
46
|
} : styles.badgeDisabled],
|
|
41
47
|
onPress: () => onToggleSource(source.source),
|
|
42
48
|
activeOpacity: 0.7,
|
|
43
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
49
|
+
children: [hasSubscriberTracking && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
50
|
+
style: [styles.countBadge, {
|
|
51
|
+
backgroundColor: isEnabled ? subscriberCount > 0 ? source.color + "25" : _sharedUi.buoyColors.textMuted + "20" : _sharedUi.buoyColors.textMuted + "15"
|
|
52
|
+
}],
|
|
53
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
54
|
+
style: [styles.countText, {
|
|
55
|
+
color: isEnabled ? subscriberCount > 0 ? source.color : _sharedUi.buoyColors.textMuted : _sharedUi.buoyColors.textMuted + "60"
|
|
56
|
+
}],
|
|
57
|
+
children: subscriberCount
|
|
58
|
+
})
|
|
59
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
44
60
|
style: [styles.dot, {
|
|
45
|
-
backgroundColor: isEnabled ? source.color : _sharedUi.buoyColors.textMuted + "
|
|
61
|
+
backgroundColor: isEnabled ? source.color : _sharedUi.buoyColors.textMuted + "40"
|
|
46
62
|
}]
|
|
47
63
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
48
64
|
style: [styles.badgeLabel, {
|
|
49
|
-
color: isEnabled ?
|
|
65
|
+
color: isEnabled ? _sharedUi.buoyColors.text : _sharedUi.buoyColors.textMuted + "70"
|
|
50
66
|
}],
|
|
51
67
|
children: source.label
|
|
52
|
-
}),
|
|
53
|
-
style: [styles.
|
|
54
|
-
|
|
68
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
69
|
+
style: [styles.countBadge, {
|
|
70
|
+
backgroundColor: isEnabled ? eventCount > 0 ? source.color + "20" : _sharedUi.buoyColors.textMuted + "15" : _sharedUi.buoyColors.textMuted + "10"
|
|
55
71
|
}],
|
|
56
|
-
children:
|
|
72
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
73
|
+
style: [styles.countText, {
|
|
74
|
+
color: isEnabled ? eventCount > 0 ? source.color : _sharedUi.buoyColors.textMuted + "80" : _sharedUi.buoyColors.textMuted + "50"
|
|
75
|
+
}],
|
|
76
|
+
children: eventCount
|
|
77
|
+
})
|
|
57
78
|
})]
|
|
58
79
|
}, source.source);
|
|
59
80
|
})
|
|
@@ -78,30 +99,38 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
78
99
|
badge: {
|
|
79
100
|
flexDirection: "row",
|
|
80
101
|
alignItems: "center",
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
borderRadius:
|
|
102
|
+
paddingVertical: 5,
|
|
103
|
+
paddingHorizontal: 6,
|
|
104
|
+
borderRadius: 20,
|
|
84
105
|
borderWidth: 1,
|
|
85
106
|
gap: 6
|
|
86
107
|
},
|
|
87
108
|
badgeDisabled: {
|
|
88
109
|
backgroundColor: _sharedUi.buoyColors.card,
|
|
89
110
|
borderColor: _sharedUi.buoyColors.border,
|
|
90
|
-
opacity: 0.
|
|
111
|
+
opacity: 0.5
|
|
91
112
|
},
|
|
92
113
|
dot: {
|
|
93
|
-
width:
|
|
94
|
-
height:
|
|
95
|
-
borderRadius:
|
|
114
|
+
width: 7,
|
|
115
|
+
height: 7,
|
|
116
|
+
borderRadius: 4
|
|
96
117
|
},
|
|
97
118
|
badgeLabel: {
|
|
98
119
|
fontSize: 12,
|
|
99
|
-
fontWeight: "
|
|
120
|
+
fontWeight: "500"
|
|
100
121
|
},
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
122
|
+
countBadge: {
|
|
123
|
+
minWidth: 18,
|
|
124
|
+
height: 18,
|
|
125
|
+
borderRadius: 9,
|
|
126
|
+
alignItems: "center",
|
|
127
|
+
justifyContent: "center",
|
|
128
|
+
paddingHorizontal: 5
|
|
129
|
+
},
|
|
130
|
+
countText: {
|
|
131
|
+
fontSize: 10,
|
|
132
|
+
fontWeight: "600",
|
|
133
|
+
fontVariant: ["tabular-nums"]
|
|
105
134
|
},
|
|
106
135
|
filterInfo: {
|
|
107
136
|
marginTop: 6,
|
|
@@ -110,6 +110,10 @@ const SOURCE_CONFIG = {
|
|
|
110
110
|
route: {
|
|
111
111
|
label: "Route",
|
|
112
112
|
color: "#06B6D4" // Cyan
|
|
113
|
+
},
|
|
114
|
+
render: {
|
|
115
|
+
label: "Render",
|
|
116
|
+
color: "#F472B6" // Pink
|
|
113
117
|
}
|
|
114
118
|
};
|
|
115
119
|
|
|
@@ -177,7 +181,8 @@ const SOURCE_BADGE_LABELS = {
|
|
|
177
181
|
"react-query": "QUERY",
|
|
178
182
|
"react-query-query": "QUERY",
|
|
179
183
|
"react-query-mutation": "MUTATION",
|
|
180
|
-
route: "ROUTE"
|
|
184
|
+
route: "ROUTE",
|
|
185
|
+
render: "RENDER"
|
|
181
186
|
};
|
|
182
187
|
|
|
183
188
|
/**
|
|
@@ -22,7 +22,7 @@ const FREE_TIER_MAX_EVENTS = 25;
|
|
|
22
22
|
/**
|
|
23
23
|
* All possible sources for display
|
|
24
24
|
*/
|
|
25
|
-
const ALL_DISPLAY_SOURCES = ["storage-async", "redux", "network", "react-query-query", "react-query-mutation", "route"];
|
|
25
|
+
const ALL_DISPLAY_SOURCES = ["storage-async", "redux", "network", "react-query-query", "react-query-mutation", "route", "render"];
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Map display sources to actual event sources they should match
|
|
@@ -35,7 +35,8 @@ const SOURCE_TO_EVENT_SOURCES = {
|
|
|
35
35
|
"react-query": ["react-query", "react-query-query"],
|
|
36
36
|
"react-query-query": ["react-query", "react-query-query"],
|
|
37
37
|
"react-query-mutation": ["react-query-mutation"],
|
|
38
|
-
route: ["route"]
|
|
38
|
+
route: ["route"],
|
|
39
|
+
render: ["render"]
|
|
39
40
|
};
|
|
40
41
|
|
|
41
42
|
/**
|
|
@@ -49,7 +50,8 @@ const EVENT_SOURCE_TO_DISCOVERY_ID = {
|
|
|
49
50
|
"react-query": "react-query",
|
|
50
51
|
"react-query-query": "react-query",
|
|
51
52
|
"react-query-mutation": "react-query",
|
|
52
|
-
route: "route-events"
|
|
53
|
+
route: "route-events",
|
|
54
|
+
render: "render"
|
|
53
55
|
};
|
|
54
56
|
function useUnifiedEvents() {
|
|
55
57
|
const {
|
|
@@ -65,6 +67,14 @@ function useUnifiedEvents() {
|
|
|
65
67
|
return (0, _unifiedEventStore.getAvailableEventSources)();
|
|
66
68
|
}, []);
|
|
67
69
|
|
|
70
|
+
// Subscribe to subscriber count changes for instant UI updates (TanStack Query pattern)
|
|
71
|
+
const [subscriberCountVersion, setSubscriberCountVersion] = (0, _react.useState)(0);
|
|
72
|
+
(0, _react.useEffect)(() => {
|
|
73
|
+
return (0, _sharedUi.subscribeToSubscriberCountChanges)(() => {
|
|
74
|
+
setSubscriberCountVersion(v => v + 1);
|
|
75
|
+
});
|
|
76
|
+
}, []);
|
|
77
|
+
|
|
68
78
|
// Get available display sources (only show sources for installed packages)
|
|
69
79
|
const availableDisplaySources = (0, _react.useMemo)(() => {
|
|
70
80
|
return ALL_DISPLAY_SOURCES.filter(displaySource => {
|
|
@@ -74,39 +84,50 @@ function useUnifiedEvents() {
|
|
|
74
84
|
});
|
|
75
85
|
}, [discoveredSources]);
|
|
76
86
|
|
|
77
|
-
// Subscribe to store changes
|
|
87
|
+
// Subscribe to store changes (always subscribe to get events when they come)
|
|
78
88
|
(0, _react.useEffect)(() => {
|
|
79
|
-
// Subscribe to store updates
|
|
80
89
|
const unsubscribe = (0, _unifiedEventStore.subscribe)(newEvents => {
|
|
81
90
|
setEvents(newEvents);
|
|
82
91
|
});
|
|
83
|
-
|
|
84
|
-
// Start capturing from all available sources
|
|
85
|
-
// These functions are now safe - they check if the source is available
|
|
86
|
-
(0, _unifiedEventStore.subscribeToStorage)();
|
|
87
|
-
(0, _unifiedEventStore.subscribeToRedux)();
|
|
88
|
-
(0, _unifiedEventStore.subscribeToNetwork)();
|
|
89
|
-
(0, _unifiedEventStore.subscribeToReactQuery)();
|
|
90
|
-
(0, _unifiedEventStore.subscribeToRoutes)();
|
|
91
92
|
return unsubscribe;
|
|
92
93
|
}, []);
|
|
93
94
|
|
|
94
|
-
// Restore saved badge selection
|
|
95
|
+
// Restore saved state on mount (badge selection + capturing state)
|
|
95
96
|
(0, _react.useEffect)(() => {
|
|
96
97
|
const restoreState = async () => {
|
|
98
|
+
// Load badge selection
|
|
97
99
|
const savedSources = await (0, _badgeSelectionStorage.loadEnabledSources)();
|
|
100
|
+
let sourcesToEnable;
|
|
98
101
|
if (savedSources && savedSources.length > 0) {
|
|
99
102
|
// Filter to only include valid sources that still exist and are available
|
|
100
103
|
const validSources = savedSources.filter(s => availableDisplaySources.includes(s));
|
|
101
104
|
if (validSources.length > 0) {
|
|
102
|
-
|
|
105
|
+
sourcesToEnable = new Set(validSources);
|
|
103
106
|
} else {
|
|
104
107
|
// If no saved sources are valid, enable all available sources
|
|
105
|
-
|
|
108
|
+
sourcesToEnable = new Set(availableDisplaySources);
|
|
106
109
|
}
|
|
107
110
|
} else {
|
|
108
111
|
// No saved state - enable all available sources
|
|
109
|
-
|
|
112
|
+
sourcesToEnable = new Set(availableDisplaySources);
|
|
113
|
+
}
|
|
114
|
+
setEnabledSources(sourcesToEnable);
|
|
115
|
+
|
|
116
|
+
// Load capturing state (default to true if not saved)
|
|
117
|
+
const savedCapturing = await (0, _badgeSelectionStorage.loadCapturingState)();
|
|
118
|
+
const shouldCapture = savedCapturing !== null ? savedCapturing : true;
|
|
119
|
+
setIsCapturing(shouldCapture);
|
|
120
|
+
|
|
121
|
+
// Start capturing if enabled - only subscribe to enabled sources
|
|
122
|
+
if (shouldCapture) {
|
|
123
|
+
if (sourcesToEnable.has("storage-async")) (0, _unifiedEventStore.subscribeToStorage)();
|
|
124
|
+
if (sourcesToEnable.has("redux")) (0, _unifiedEventStore.subscribeToRedux)();
|
|
125
|
+
if (sourcesToEnable.has("network")) (0, _unifiedEventStore.subscribeToNetwork)();
|
|
126
|
+
if (sourcesToEnable.has("react-query-query") || sourcesToEnable.has("react-query-mutation")) {
|
|
127
|
+
(0, _unifiedEventStore.subscribeToReactQuery)();
|
|
128
|
+
}
|
|
129
|
+
if (sourcesToEnable.has("route")) (0, _unifiedEventStore.subscribeToRoutes)();
|
|
130
|
+
if (sourcesToEnable.has("render")) (0, _unifiedEventStore.subscribeToRender)();
|
|
110
131
|
}
|
|
111
132
|
isStateRestoredRef.current = true;
|
|
112
133
|
};
|
|
@@ -121,6 +142,14 @@ function useUnifiedEvents() {
|
|
|
121
142
|
(0, _badgeSelectionStorage.saveEnabledSources)(Array.from(enabledSources));
|
|
122
143
|
}, [enabledSources]);
|
|
123
144
|
|
|
145
|
+
// Persist capturing state whenever it changes (after initial restoration)
|
|
146
|
+
(0, _react.useEffect)(() => {
|
|
147
|
+
if (!isStateRestoredRef.current) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
(0, _badgeSelectionStorage.saveCapturingState)(isCapturing);
|
|
151
|
+
}, [isCapturing]);
|
|
152
|
+
|
|
124
153
|
// Build set of all event sources that should be shown
|
|
125
154
|
const allowedEventSources = (0, _react.useMemo)(() => {
|
|
126
155
|
const allowed = new Set();
|
|
@@ -160,15 +189,40 @@ function useUnifiedEvents() {
|
|
|
160
189
|
// Get all available sources with counts, sorted: enabled first, disabled last
|
|
161
190
|
const availableSources = (0, _react.useMemo)(() => {
|
|
162
191
|
const counts = (0, _unifiedEventStore.getSourceCounts)();
|
|
192
|
+
const subscriberCounts = (0, _unifiedEventStore.getSubscriberCounts)();
|
|
193
|
+
|
|
194
|
+
// Build a map from source ID to subscriber count
|
|
195
|
+
const subscriberCountBySourceId = {};
|
|
196
|
+
for (const source of subscriberCounts.sources) {
|
|
197
|
+
subscriberCountBySourceId[source.sourceId] = source.counts.total;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Map display source to store source ID
|
|
201
|
+
const displaySourceToStoreId = {
|
|
202
|
+
"storage-async": "storage",
|
|
203
|
+
"storage-mmkv": "storage",
|
|
204
|
+
redux: "redux",
|
|
205
|
+
network: "network",
|
|
206
|
+
"react-query": "react-query",
|
|
207
|
+
"react-query-query": "react-query",
|
|
208
|
+
"react-query-mutation": "react-query",
|
|
209
|
+
route: "route-events",
|
|
210
|
+
render: "render"
|
|
211
|
+
};
|
|
163
212
|
const sources = availableDisplaySources.map(source => {
|
|
164
213
|
const eventSources = SOURCE_TO_EVENT_SOURCES[source] || [source];
|
|
165
214
|
const totalCount = eventSources.reduce((sum, s) => sum + (counts[s] || 0), 0);
|
|
166
215
|
const displayConfig = (0, _autoDiscoverEventSources.getSourceDisplayConfig)(source);
|
|
216
|
+
const storeId = displaySourceToStoreId[source];
|
|
217
|
+
// Only set subscriberCount if the source has subscriber tracking
|
|
218
|
+
// (undefined means no tracking, vs 0 which means tracked but no subscribers)
|
|
219
|
+
const subscriberCount = storeId && storeId in subscriberCountBySourceId ? subscriberCountBySourceId[storeId] : undefined;
|
|
167
220
|
return {
|
|
168
221
|
source,
|
|
169
222
|
...displayConfig,
|
|
170
223
|
count: totalCount,
|
|
171
|
-
enabled: enabledSources.has(source)
|
|
224
|
+
enabled: enabledSources.has(source),
|
|
225
|
+
subscriberCount
|
|
172
226
|
};
|
|
173
227
|
});
|
|
174
228
|
|
|
@@ -178,18 +232,65 @@ function useUnifiedEvents() {
|
|
|
178
232
|
if (!a.enabled && b.enabled) return 1;
|
|
179
233
|
return 0;
|
|
180
234
|
});
|
|
181
|
-
}, [events, enabledSources, availableDisplaySources]);
|
|
235
|
+
}, [events, enabledSources, availableDisplaySources, subscriberCountVersion]);
|
|
182
236
|
const toggleSource = (0, _react.useCallback)(source => {
|
|
183
237
|
setEnabledSources(prev => {
|
|
184
238
|
const next = new Set(prev);
|
|
185
|
-
|
|
239
|
+
const wasEnabled = next.has(source);
|
|
240
|
+
if (wasEnabled) {
|
|
186
241
|
next.delete(source);
|
|
242
|
+
// Unsubscribe from the source
|
|
243
|
+
switch (source) {
|
|
244
|
+
case "storage-async":
|
|
245
|
+
(0, _unifiedEventStore.unsubscribeFromStorage)();
|
|
246
|
+
break;
|
|
247
|
+
case "redux":
|
|
248
|
+
(0, _unifiedEventStore.unsubscribeFromRedux)();
|
|
249
|
+
break;
|
|
250
|
+
case "network":
|
|
251
|
+
(0, _unifiedEventStore.unsubscribeFromNetwork)();
|
|
252
|
+
break;
|
|
253
|
+
case "react-query-query":
|
|
254
|
+
case "react-query-mutation":
|
|
255
|
+
(0, _unifiedEventStore.unsubscribeFromReactQuery)();
|
|
256
|
+
break;
|
|
257
|
+
case "route":
|
|
258
|
+
(0, _unifiedEventStore.unsubscribeFromRoutes)();
|
|
259
|
+
break;
|
|
260
|
+
case "render":
|
|
261
|
+
(0, _unifiedEventStore.unsubscribeFromRender)();
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
187
264
|
} else {
|
|
188
265
|
next.add(source);
|
|
266
|
+
// Subscribe to the source (only if capturing is active)
|
|
267
|
+
if (isCapturing) {
|
|
268
|
+
switch (source) {
|
|
269
|
+
case "storage-async":
|
|
270
|
+
(0, _unifiedEventStore.subscribeToStorage)();
|
|
271
|
+
break;
|
|
272
|
+
case "redux":
|
|
273
|
+
(0, _unifiedEventStore.subscribeToRedux)();
|
|
274
|
+
break;
|
|
275
|
+
case "network":
|
|
276
|
+
(0, _unifiedEventStore.subscribeToNetwork)();
|
|
277
|
+
break;
|
|
278
|
+
case "react-query-query":
|
|
279
|
+
case "react-query-mutation":
|
|
280
|
+
(0, _unifiedEventStore.subscribeToReactQuery)();
|
|
281
|
+
break;
|
|
282
|
+
case "route":
|
|
283
|
+
(0, _unifiedEventStore.subscribeToRoutes)();
|
|
284
|
+
break;
|
|
285
|
+
case "render":
|
|
286
|
+
(0, _unifiedEventStore.subscribeToRender)();
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
189
290
|
}
|
|
190
291
|
return next;
|
|
191
292
|
});
|
|
192
|
-
}, []);
|
|
293
|
+
}, [isCapturing]);
|
|
193
294
|
const enableAllSources = (0, _react.useCallback)(() => {
|
|
194
295
|
setEnabledSources(new Set(availableDisplaySources));
|
|
195
296
|
}, [availableDisplaySources]);
|
|
@@ -197,13 +298,17 @@ function useUnifiedEvents() {
|
|
|
197
298
|
(0, _unifiedEventStore.clearEvents)();
|
|
198
299
|
}, []);
|
|
199
300
|
const startCapturing = (0, _react.useCallback)(() => {
|
|
200
|
-
|
|
201
|
-
(0, _unifiedEventStore.
|
|
202
|
-
(0, _unifiedEventStore.
|
|
203
|
-
(0, _unifiedEventStore.
|
|
204
|
-
(
|
|
301
|
+
// Only subscribe to sources that are enabled
|
|
302
|
+
if (enabledSources.has("storage-async")) (0, _unifiedEventStore.subscribeToStorage)();
|
|
303
|
+
if (enabledSources.has("redux")) (0, _unifiedEventStore.subscribeToRedux)();
|
|
304
|
+
if (enabledSources.has("network")) (0, _unifiedEventStore.subscribeToNetwork)();
|
|
305
|
+
if (enabledSources.has("react-query-query") || enabledSources.has("react-query-mutation")) {
|
|
306
|
+
(0, _unifiedEventStore.subscribeToReactQuery)();
|
|
307
|
+
}
|
|
308
|
+
if (enabledSources.has("route")) (0, _unifiedEventStore.subscribeToRoutes)();
|
|
309
|
+
if (enabledSources.has("render")) (0, _unifiedEventStore.subscribeToRender)();
|
|
205
310
|
setIsCapturing(true);
|
|
206
|
-
}, []);
|
|
311
|
+
}, [enabledSources]);
|
|
207
312
|
const stopCapturing = (0, _react.useCallback)(() => {
|
|
208
313
|
(0, _unifiedEventStore.unsubscribeAll)();
|
|
209
314
|
setIsCapturing(false);
|
|
@@ -215,6 +320,9 @@ function useUnifiedEvents() {
|
|
|
215
320
|
startCapturing();
|
|
216
321
|
}
|
|
217
322
|
}, [isCapturing, startCapturing, stopCapturing]);
|
|
323
|
+
|
|
324
|
+
// Get subscriber counts (recalculates on every render, but it's a cheap operation)
|
|
325
|
+
const totalSubscriberCount = (0, _unifiedEventStore.getSubscriberCounts)().totalSubscribers;
|
|
218
326
|
return {
|
|
219
327
|
events,
|
|
220
328
|
filteredEvents,
|
|
@@ -231,7 +339,8 @@ function useUnifiedEvents() {
|
|
|
231
339
|
toggleCapturing,
|
|
232
340
|
discoveredSources,
|
|
233
341
|
hiddenEventsCount,
|
|
234
|
-
isPro
|
|
342
|
+
isPro,
|
|
343
|
+
totalSubscriberCount
|
|
235
344
|
};
|
|
236
345
|
}
|
|
237
346
|
//# sourceMappingURL=useUnifiedEvents.js.map
|
package/lib/commonjs/index.js
CHANGED
|
@@ -129,6 +129,12 @@ Object.defineProperty(exports, "generateMarkdownExport", {
|
|
|
129
129
|
return _eventExportFormatter.generateMarkdownExport;
|
|
130
130
|
}
|
|
131
131
|
});
|
|
132
|
+
Object.defineProperty(exports, "generateMermaidExport", {
|
|
133
|
+
enumerable: true,
|
|
134
|
+
get: function () {
|
|
135
|
+
return _eventExportFormatter.generateMermaidExport;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
132
138
|
Object.defineProperty(exports, "generatePlaintextExport", {
|
|
133
139
|
enumerable: true,
|
|
134
140
|
get: function () {
|