@buoy-gg/route-events 7.0.33 → 7.0.35
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/NavigationStack.js +11 -11
- package/lib/commonjs/components/ReactNavigationRoutes.js +15 -15
- package/lib/commonjs/components/RouteEventDetail.js +1 -1
- package/lib/commonjs/components/RouteEventExpandedContent.js +3 -3
- package/lib/commonjs/components/RouteEventItemCompact.js +2 -2
- package/lib/commonjs/components/RouteEventsModalWithTabs.js +24 -107
- package/lib/commonjs/components/RouteEventsTimeline.js +4 -13
- package/lib/commonjs/components/RoutesSitemap.js +16 -16
- package/lib/commonjs/hooks/useRouteEvents.js +12 -43
- package/lib/commonjs/preset.js +7 -21
- package/lib/module/components/NavigationStack.js +12 -12
- package/lib/module/components/ReactNavigationRoutes.js +16 -16
- package/lib/module/components/RouteEventDetail.js +2 -2
- package/lib/module/components/RouteEventExpandedContent.js +4 -4
- package/lib/module/components/RouteEventItemCompact.js +3 -3
- package/lib/module/components/RouteEventsModalWithTabs.js +26 -109
- package/lib/module/components/RouteEventsTimeline.js +5 -14
- package/lib/module/components/RoutesSitemap.js +17 -17
- package/lib/module/hooks/useRouteEvents.js +12 -43
- package/lib/module/preset.js +6 -19
- package/lib/typescript/components/NavigationStack.d.ts.map +1 -1
- package/lib/typescript/components/ReactNavigationRoutes.d.ts.map +1 -1
- package/lib/typescript/components/RouteEventsModalWithTabs.d.ts.map +1 -1
- package/lib/typescript/components/RouteEventsTimeline.d.ts.map +1 -1
- package/lib/typescript/components/RoutesSitemap.d.ts.map +1 -1
- package/lib/typescript/hooks/useRouteEvents.d.ts.map +1 -1
- package/lib/typescript/preset.d.ts +2 -8
- package/lib/typescript/preset.d.ts.map +1 -1
- package/package.json +5 -5
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.useRouteEvents = useRouteEvents;
|
|
7
|
-
var
|
|
7
|
+
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
8
8
|
var _routeEventStore = require("../stores/routeEventStore");
|
|
9
9
|
/**
|
|
10
10
|
* useRouteEvents Hook
|
|
@@ -39,50 +39,19 @@ function useRouteEvents(options = {}) {
|
|
|
39
39
|
maxEvents = 500,
|
|
40
40
|
enabled = true
|
|
41
41
|
} = options;
|
|
42
|
-
|
|
43
|
-
//
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Frame-coalesced (see network's useNetworkEventList): navigation
|
|
56
|
-
// bursts land as one commit per frame instead of one per emission.
|
|
57
|
-
let rafId = null;
|
|
58
|
-
let pending = null;
|
|
59
|
-
const unsubscribe = _routeEventStore.routeEventStore.subscribeToEvents(allEvents => {
|
|
60
|
-
pending = allEvents;
|
|
61
|
-
if (rafId != null) return;
|
|
62
|
-
rafId = requestAnimationFrame(() => {
|
|
63
|
-
rafId = null;
|
|
64
|
-
if (!pending) return;
|
|
65
|
-
const latest = pending;
|
|
66
|
-
pending = null;
|
|
67
|
-
setEvents(latest.length > maxEvents ? latest.slice(0, maxEvents) : latest);
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// Mark as listening after successful subscription
|
|
72
|
-
setIsListening(true);
|
|
73
|
-
return () => {
|
|
74
|
-
unsubscribe();
|
|
75
|
-
if (rafId != null) cancelAnimationFrame(rafId);
|
|
76
|
-
// Note: Don't set isListening=false here because we might be
|
|
77
|
-
// re-subscribing due to dependency change, not actually stopping
|
|
78
|
-
};
|
|
79
|
-
}, [maxEvents, enabled]);
|
|
80
|
-
const clearEvents = (0, _react.useCallback)(() => {
|
|
81
|
-
_routeEventStore.routeEventStore.clearEvents();
|
|
82
|
-
}, []);
|
|
42
|
+
// Subscribing auto-starts the route observer (Subscribable pattern), and
|
|
43
|
+
// the shared hook frame-coalesces navigation bursts into one commit.
|
|
44
|
+
const {
|
|
45
|
+
events,
|
|
46
|
+
clearEvents,
|
|
47
|
+
isActive
|
|
48
|
+
} = (0, _sharedUi.useEventStoreEvents)(_routeEventStore.routeEventStore, {
|
|
49
|
+
maxEvents,
|
|
50
|
+
enabled
|
|
51
|
+
});
|
|
83
52
|
return {
|
|
84
53
|
events,
|
|
85
54
|
clearEvents,
|
|
86
|
-
isListening
|
|
55
|
+
isListening: isActive
|
|
87
56
|
};
|
|
88
57
|
}
|
package/lib/commonjs/preset.js
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.createRouteEventsTool =
|
|
7
|
-
exports.routeEventsToolPreset = void 0;
|
|
6
|
+
exports.routeEventsToolPreset = exports.createRouteEventsTool = void 0;
|
|
8
7
|
var _floatingToolsCore = require("@buoy-gg/floating-tools-core");
|
|
9
8
|
var _RouteEventsModalWithTabs = require("./components/RouteEventsModalWithTabs");
|
|
9
|
+
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
10
10
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
11
11
|
/**
|
|
12
12
|
* Pre-configured route events tool for FloatingDevTools
|
|
@@ -33,7 +33,7 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
33
33
|
* - Navigation stack visualization
|
|
34
34
|
* - Automatic route tracking (no setup needed)
|
|
35
35
|
*/
|
|
36
|
-
const routeEventsToolPreset = exports.routeEventsToolPreset = {
|
|
36
|
+
const routeEventsToolPreset = exports.routeEventsToolPreset = (0, _sharedUi.defineToolPreset)({
|
|
37
37
|
id: "route-events",
|
|
38
38
|
name: "ROUTES",
|
|
39
39
|
description: "Route tracking & navigation inspector",
|
|
@@ -47,7 +47,7 @@ const routeEventsToolPreset = exports.routeEventsToolPreset = {
|
|
|
47
47
|
props: {
|
|
48
48
|
enableSharedModalDimensions: false
|
|
49
49
|
}
|
|
50
|
-
};
|
|
50
|
+
});
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
53
|
* Create a custom route events tool configuration.
|
|
@@ -64,20 +64,6 @@ const routeEventsToolPreset = exports.routeEventsToolPreset = {
|
|
|
64
64
|
* });
|
|
65
65
|
* ```
|
|
66
66
|
*/
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
name: options?.name || "ROUTES",
|
|
71
|
-
description: options?.description || "Route tracking & navigation inspector",
|
|
72
|
-
slot: "both",
|
|
73
|
-
icon: ({
|
|
74
|
-
size
|
|
75
|
-
}) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.RoutesIcon, {
|
|
76
|
-
size: size
|
|
77
|
-
}),
|
|
78
|
-
component: _RouteEventsModalWithTabs.RouteEventsModalWithTabs,
|
|
79
|
-
props: {
|
|
80
|
-
enableSharedModalDimensions: options?.enableSharedModalDimensions !== undefined ? options.enableSharedModalDimensions : false
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
}
|
|
67
|
+
const createRouteEventsTool = exports.createRouteEventsTool = (0, _sharedUi.createToolFactory)(routeEventsToolPreset, options => ({
|
|
68
|
+
enableSharedModalDimensions: options.enableSharedModalDimensions ?? false
|
|
69
|
+
}));
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import { useState, useMemo, useEffect } from "react";
|
|
11
11
|
import { View, Text, ScrollView, TouchableOpacity, StyleSheet, Alert } from "react-native";
|
|
12
|
-
import { ChevronDown, ChevronRight, InlineCopyButton, ProUpgradeModal, buoyColors, night, useSafeAreaInsets, ToolEmptyState } from "@buoy-gg/shared-ui";
|
|
12
|
+
import { ChevronDown, ChevronRight, InlineCopyButton, ProUpgradeModal, buoyColors, night, useSafeAreaInsets, ToolEmptyState, monoFont } from "@buoy-gg/shared-ui";
|
|
13
13
|
import { useIsPro } from "@buoy-gg/license";
|
|
14
14
|
import { DataViewer } from "@buoy-gg/shared-ui/dataViewer";
|
|
15
15
|
import { useNavigationStack } from "../useNavigationStack";
|
|
@@ -412,7 +412,7 @@ const styles = StyleSheet.create({
|
|
|
412
412
|
loadingText: {
|
|
413
413
|
color: night.color.textSecondary,
|
|
414
414
|
fontSize: 14,
|
|
415
|
-
fontFamily:
|
|
415
|
+
fontFamily: monoFont
|
|
416
416
|
},
|
|
417
417
|
errorContainer: {
|
|
418
418
|
flex: 1,
|
|
@@ -424,13 +424,13 @@ const styles = StyleSheet.create({
|
|
|
424
424
|
color: buoyColors.error,
|
|
425
425
|
fontSize: 16,
|
|
426
426
|
fontWeight: "600",
|
|
427
|
-
fontFamily:
|
|
427
|
+
fontFamily: monoFont,
|
|
428
428
|
marginBottom: 8
|
|
429
429
|
},
|
|
430
430
|
errorDetail: {
|
|
431
431
|
color: night.color.textSecondary,
|
|
432
432
|
fontSize: 12,
|
|
433
|
-
fontFamily:
|
|
433
|
+
fontFamily: monoFont,
|
|
434
434
|
textAlign: "center"
|
|
435
435
|
},
|
|
436
436
|
emptyContainer: {
|
|
@@ -443,13 +443,13 @@ const styles = StyleSheet.create({
|
|
|
443
443
|
color: night.color.text,
|
|
444
444
|
fontSize: 16,
|
|
445
445
|
fontWeight: "600",
|
|
446
|
-
fontFamily:
|
|
446
|
+
fontFamily: monoFont,
|
|
447
447
|
marginBottom: 8
|
|
448
448
|
},
|
|
449
449
|
emptySubtext: {
|
|
450
450
|
color: night.color.textSecondary,
|
|
451
451
|
fontSize: 14,
|
|
452
|
-
fontFamily:
|
|
452
|
+
fontFamily: monoFont,
|
|
453
453
|
textAlign: "center"
|
|
454
454
|
},
|
|
455
455
|
stackScroll: {
|
|
@@ -487,7 +487,7 @@ const styles = StyleSheet.create({
|
|
|
487
487
|
fontSize: 13,
|
|
488
488
|
fontWeight: "600",
|
|
489
489
|
color: night.color.text,
|
|
490
|
-
fontFamily:
|
|
490
|
+
fontFamily: monoFont,
|
|
491
491
|
flex: 1
|
|
492
492
|
},
|
|
493
493
|
copyRouteButton: {
|
|
@@ -503,7 +503,7 @@ const styles = StyleSheet.create({
|
|
|
503
503
|
statusBadgeText: {
|
|
504
504
|
fontSize: 10,
|
|
505
505
|
fontWeight: "600",
|
|
506
|
-
fontFamily:
|
|
506
|
+
fontFamily: monoFont
|
|
507
507
|
},
|
|
508
508
|
expandedContent: {
|
|
509
509
|
paddingHorizontal: 12,
|
|
@@ -518,13 +518,13 @@ const styles = StyleSheet.create({
|
|
|
518
518
|
detailLabel: {
|
|
519
519
|
fontSize: 10,
|
|
520
520
|
color: night.color.textSecondary,
|
|
521
|
-
fontFamily:
|
|
521
|
+
fontFamily: monoFont,
|
|
522
522
|
marginBottom: 2
|
|
523
523
|
},
|
|
524
524
|
detailValue: {
|
|
525
525
|
fontSize: 12,
|
|
526
526
|
color: night.color.text,
|
|
527
|
-
fontFamily:
|
|
527
|
+
fontFamily: monoFont
|
|
528
528
|
},
|
|
529
529
|
dataViewerContainer: {
|
|
530
530
|
marginTop: 4,
|
|
@@ -553,7 +553,7 @@ const styles = StyleSheet.create({
|
|
|
553
553
|
fontSize: 12,
|
|
554
554
|
fontWeight: "600",
|
|
555
555
|
color: night.color.text,
|
|
556
|
-
fontFamily:
|
|
556
|
+
fontFamily: monoFont
|
|
557
557
|
},
|
|
558
558
|
actionButtonTextDisabled: {
|
|
559
559
|
color: night.color.textTertiary
|
|
@@ -561,7 +561,7 @@ const styles = StyleSheet.create({
|
|
|
561
561
|
helpText: {
|
|
562
562
|
fontSize: 9,
|
|
563
563
|
color: night.color.textSecondary,
|
|
564
|
-
fontFamily:
|
|
564
|
+
fontFamily: monoFont,
|
|
565
565
|
textAlign: "center",
|
|
566
566
|
marginTop: 4,
|
|
567
567
|
lineHeight: 12
|
|
@@ -18,7 +18,7 @@ import { getCommonActions, useSafeNavigationContainerRef } from "../utils/safeRe
|
|
|
18
18
|
// (useSafeNavigationContainerRef then yields undefined, so the dispatch
|
|
19
19
|
// paths below never execute).
|
|
20
20
|
const CommonActions = getCommonActions();
|
|
21
|
-
import { Search, ChevronDown, ChevronRight, InlineCopyButton, ToolbarCopyButton, RefreshCw, ProUpgradeModal, buoyColors, night } from "@buoy-gg/shared-ui";
|
|
21
|
+
import { Search, ChevronDown, ChevronRight, InlineCopyButton, ToolbarCopyButton, RefreshCw, ProUpgradeModal, buoyColors, night, monoFont } from "@buoy-gg/shared-ui";
|
|
22
22
|
import { useIsPro } from "@buoy-gg/license";
|
|
23
23
|
|
|
24
24
|
// ============================================================================
|
|
@@ -546,12 +546,12 @@ const styles = StyleSheet.create({
|
|
|
546
546
|
emptyText: {
|
|
547
547
|
color: night.color.textSecondary,
|
|
548
548
|
fontSize: 14,
|
|
549
|
-
fontFamily:
|
|
549
|
+
fontFamily: monoFont
|
|
550
550
|
},
|
|
551
551
|
emptySubtext: {
|
|
552
552
|
color: night.color.textTertiary,
|
|
553
553
|
fontSize: 12,
|
|
554
|
-
fontFamily:
|
|
554
|
+
fontFamily: monoFont,
|
|
555
555
|
marginTop: 8
|
|
556
556
|
},
|
|
557
557
|
header: {
|
|
@@ -589,7 +589,7 @@ const styles = StyleSheet.create({
|
|
|
589
589
|
actionLabel: {
|
|
590
590
|
fontSize: 8,
|
|
591
591
|
color: night.color.textTertiary,
|
|
592
|
-
fontFamily:
|
|
592
|
+
fontFamily: monoFont,
|
|
593
593
|
textTransform: "uppercase",
|
|
594
594
|
letterSpacing: 0.5
|
|
595
595
|
},
|
|
@@ -616,13 +616,13 @@ const styles = StyleSheet.create({
|
|
|
616
616
|
fontSize: 18,
|
|
617
617
|
fontWeight: "800",
|
|
618
618
|
color: night.color.text,
|
|
619
|
-
fontFamily:
|
|
619
|
+
fontFamily: monoFont
|
|
620
620
|
},
|
|
621
621
|
statLabel: {
|
|
622
622
|
fontSize: 10,
|
|
623
623
|
color: night.color.textTertiary,
|
|
624
624
|
marginTop: 4,
|
|
625
|
-
fontFamily:
|
|
625
|
+
fontFamily: monoFont,
|
|
626
626
|
textTransform: "uppercase",
|
|
627
627
|
letterSpacing: 0.5
|
|
628
628
|
},
|
|
@@ -638,7 +638,7 @@ const styles = StyleSheet.create({
|
|
|
638
638
|
flex: 1,
|
|
639
639
|
color: night.color.text,
|
|
640
640
|
fontSize: 14,
|
|
641
|
-
fontFamily:
|
|
641
|
+
fontFamily: monoFont
|
|
642
642
|
},
|
|
643
643
|
clearButton: {
|
|
644
644
|
padding: 4
|
|
@@ -655,7 +655,7 @@ const styles = StyleSheet.create({
|
|
|
655
655
|
color: night.color.accent,
|
|
656
656
|
fontSize: 14,
|
|
657
657
|
fontWeight: "600",
|
|
658
|
-
fontFamily:
|
|
658
|
+
fontFamily: monoFont
|
|
659
659
|
},
|
|
660
660
|
scrollView: {
|
|
661
661
|
flex: 1
|
|
@@ -677,7 +677,7 @@ const styles = StyleSheet.create({
|
|
|
677
677
|
metaText: {
|
|
678
678
|
fontSize: 12,
|
|
679
679
|
color: night.color.textSecondary,
|
|
680
|
-
fontFamily:
|
|
680
|
+
fontFamily: monoFont
|
|
681
681
|
},
|
|
682
682
|
sourceBadge: {
|
|
683
683
|
paddingHorizontal: 8,
|
|
@@ -691,7 +691,7 @@ const styles = StyleSheet.create({
|
|
|
691
691
|
fontSize: 11,
|
|
692
692
|
color: night.color.textSecondary,
|
|
693
693
|
textTransform: "capitalize",
|
|
694
|
-
fontFamily:
|
|
694
|
+
fontFamily: monoFont
|
|
695
695
|
},
|
|
696
696
|
groupContainer: {
|
|
697
697
|
marginVertical: 4
|
|
@@ -716,7 +716,7 @@ const styles = StyleSheet.create({
|
|
|
716
716
|
fontSize: 12,
|
|
717
717
|
fontWeight: "700",
|
|
718
718
|
color: night.color.text,
|
|
719
|
-
fontFamily:
|
|
719
|
+
fontFamily: monoFont,
|
|
720
720
|
textTransform: "uppercase",
|
|
721
721
|
letterSpacing: 0.8
|
|
722
722
|
},
|
|
@@ -735,7 +735,7 @@ const styles = StyleSheet.create({
|
|
|
735
735
|
fontSize: 11,
|
|
736
736
|
fontWeight: "600",
|
|
737
737
|
color: "#3B82F6",
|
|
738
|
-
fontFamily:
|
|
738
|
+
fontFamily: monoFont
|
|
739
739
|
},
|
|
740
740
|
screensList: {
|
|
741
741
|
// Transparent so the night sheet's star field shows through.
|
|
@@ -752,7 +752,7 @@ const styles = StyleSheet.create({
|
|
|
752
752
|
groupDescriptionText: {
|
|
753
753
|
fontSize: 11,
|
|
754
754
|
color: night.color.textSecondary,
|
|
755
|
-
fontFamily:
|
|
755
|
+
fontFamily: monoFont,
|
|
756
756
|
lineHeight: 16
|
|
757
757
|
},
|
|
758
758
|
screenItem: {
|
|
@@ -791,7 +791,7 @@ const styles = StyleSheet.create({
|
|
|
791
791
|
fontSize: 13,
|
|
792
792
|
fontWeight: "600",
|
|
793
793
|
color: night.color.text,
|
|
794
|
-
fontFamily:
|
|
794
|
+
fontFamily: monoFont,
|
|
795
795
|
flex: 1
|
|
796
796
|
},
|
|
797
797
|
screenHeaderActions: {
|
|
@@ -808,7 +808,7 @@ const styles = StyleSheet.create({
|
|
|
808
808
|
statusText: {
|
|
809
809
|
fontSize: 10,
|
|
810
810
|
fontWeight: "600",
|
|
811
|
-
fontFamily:
|
|
811
|
+
fontFamily: monoFont
|
|
812
812
|
},
|
|
813
813
|
headerActionButton: {
|
|
814
814
|
padding: 6,
|
|
@@ -826,7 +826,7 @@ const styles = StyleSheet.create({
|
|
|
826
826
|
navigateButtonText: {
|
|
827
827
|
fontSize: 12,
|
|
828
828
|
color: night.color.accent,
|
|
829
|
-
fontFamily:
|
|
829
|
+
fontFamily: monoFont,
|
|
830
830
|
fontWeight: "600"
|
|
831
831
|
}
|
|
832
832
|
});
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { View, Text, StyleSheet, TouchableOpacity, ScrollView } from "react-native";
|
|
13
|
-
import { Navigation, night } from "@buoy-gg/shared-ui";
|
|
13
|
+
import { Navigation, night, monoFont } from "@buoy-gg/shared-ui";
|
|
14
14
|
import { RouteEventExpandedContent } from "./RouteEventExpandedContent";
|
|
15
15
|
import { getRouteTemplate } from "../utils/routeTemplate";
|
|
16
16
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
@@ -86,7 +86,7 @@ const styles = StyleSheet.create({
|
|
|
86
86
|
fontWeight: "600",
|
|
87
87
|
// Ink on a filled accent surface — the night accent takes dark ink.
|
|
88
88
|
color: night.color.onAccent,
|
|
89
|
-
fontFamily:
|
|
89
|
+
fontFamily: monoFont,
|
|
90
90
|
textTransform: "uppercase",
|
|
91
91
|
letterSpacing: 0.5
|
|
92
92
|
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { View, Text, StyleSheet } from "react-native";
|
|
13
|
-
import { InlineCopyButton, night } from "@buoy-gg/shared-ui";
|
|
13
|
+
import { InlineCopyButton, night, monoFont } from "@buoy-gg/shared-ui";
|
|
14
14
|
import { DataViewer } from "@buoy-gg/shared-ui/dataViewer";
|
|
15
15
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
16
16
|
// Format duration in milliseconds to human-readable string
|
|
@@ -168,14 +168,14 @@ const styles = StyleSheet.create({
|
|
|
168
168
|
detailLabel: {
|
|
169
169
|
fontSize: 10,
|
|
170
170
|
color: night.color.textSecondary,
|
|
171
|
-
fontFamily:
|
|
171
|
+
fontFamily: monoFont,
|
|
172
172
|
fontWeight: "600",
|
|
173
173
|
minWidth: 70
|
|
174
174
|
},
|
|
175
175
|
detailValue: {
|
|
176
176
|
fontSize: 11,
|
|
177
177
|
color: night.color.text,
|
|
178
|
-
fontFamily:
|
|
178
|
+
fontFamily: monoFont,
|
|
179
179
|
flex: 1
|
|
180
180
|
},
|
|
181
181
|
copyButton: {
|
|
@@ -194,7 +194,7 @@ const styles = StyleSheet.create({
|
|
|
194
194
|
dataViewerTitle: {
|
|
195
195
|
fontSize: 11,
|
|
196
196
|
color: night.color.textSecondary,
|
|
197
|
-
fontFamily:
|
|
197
|
+
fontFamily: monoFont,
|
|
198
198
|
fontWeight: "600"
|
|
199
199
|
}
|
|
200
200
|
});
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import { memo, useMemo } from "react";
|
|
10
10
|
import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
|
|
11
|
-
import { CompactRow, RelativeTime, buoyColors, night } from "@buoy-gg/shared-ui";
|
|
11
|
+
import { CompactRow, RelativeTime, buoyColors, night, monoFont } from "@buoy-gg/shared-ui";
|
|
12
12
|
import { RouteEventExpandedContent } from "./RouteEventExpandedContent";
|
|
13
13
|
import { getRouteTemplate } from "../utils/routeTemplate";
|
|
14
14
|
import { eventRowTestID } from "../utils/testIDs";
|
|
@@ -187,7 +187,7 @@ const styles = StyleSheet.create({
|
|
|
187
187
|
badgeText: {
|
|
188
188
|
fontSize: 11,
|
|
189
189
|
fontWeight: "600",
|
|
190
|
-
fontFamily:
|
|
190
|
+
fontFamily: monoFont
|
|
191
191
|
},
|
|
192
192
|
goButton: {
|
|
193
193
|
backgroundColor: night.color.accent,
|
|
@@ -200,6 +200,6 @@ const styles = StyleSheet.create({
|
|
|
200
200
|
fontWeight: "600",
|
|
201
201
|
// Ink on a filled accent surface — the night accent takes dark ink.
|
|
202
202
|
color: night.color.onAccent,
|
|
203
|
-
fontFamily:
|
|
203
|
+
fontFamily: monoFont
|
|
204
204
|
}
|
|
205
205
|
});
|
|
@@ -8,8 +8,8 @@ import { getCommonActions, useSafeNavigationContainerRef } from "../utils/safeRe
|
|
|
8
8
|
// (useSafeNavigationContainerRef then yields undefined, so the dispatch
|
|
9
9
|
// paths below never execute).
|
|
10
10
|
const CommonActions = getCommonActions();
|
|
11
|
-
import { useSafeRouter, isExpoRouterAvailable, windowDragProps, ToolEmptyState, resolveListEmptyState } from "@buoy-gg/shared-ui";
|
|
12
|
-
import { JsModal, ModalHeader, TabSelector, formatRelativeTime, devToolsStorageKeys, Trash2, Filter, SearchBar,
|
|
11
|
+
import { useSafeRouter, isExpoRouterAvailable, windowDragProps, ToolEmptyState, resolveListEmptyState, usePersistedState, monoFont } from "@buoy-gg/shared-ui";
|
|
12
|
+
import { JsModal, ModalHeader, TabSelector, formatRelativeTime, devToolsStorageKeys, Trash2, Filter, SearchBar, ToolbarCopyButton, Lock, ProUpgradeModal, PowerToggleButton, buoyColors, night, TickProvider, useLimit } from "@buoy-gg/shared-ui";
|
|
13
13
|
import { useIsPro } from "@buoy-gg/license";
|
|
14
14
|
|
|
15
15
|
// Free tier limit for route events
|
|
@@ -22,6 +22,23 @@ import { ReactNavigationRoutes } from "./ReactNavigationRoutes";
|
|
|
22
22
|
import { NavigationStack } from "./NavigationStack";
|
|
23
23
|
import { RouteEventsTimeline } from "./RouteEventsTimeline";
|
|
24
24
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
25
|
+
/** Persistence recipes: the tab is stored as its bare name, the flag as "true"/"false". */
|
|
26
|
+
const TAB_PERSISTENCE = {
|
|
27
|
+
// Every tab the selector offers, including "stack": the save side has
|
|
28
|
+
// always written it, so leaving it off this list meant the Stack tab
|
|
29
|
+
// was persisted and then silently discarded on the next launch.
|
|
30
|
+
parse: raw => raw === "routes" || raw === "events" || raw === "stack" ? raw : undefined,
|
|
31
|
+
serialize: tab => tab
|
|
32
|
+
};
|
|
33
|
+
const BOOLEAN_PERSISTENCE = {
|
|
34
|
+
parse: raw => raw === "true",
|
|
35
|
+
serialize: value => value.toString()
|
|
36
|
+
};
|
|
37
|
+
const STRING_SET_PERSISTENCE = {
|
|
38
|
+
parse: raw => new Set(JSON.parse(raw)),
|
|
39
|
+
serialize: set => JSON.stringify(Array.from(set))
|
|
40
|
+
};
|
|
41
|
+
|
|
25
42
|
/**
|
|
26
43
|
* Find the path from root navigation state to a screen by name.
|
|
27
44
|
* Returns array of route names from root to the target, or null if not found.
|
|
@@ -82,7 +99,7 @@ export function RouteEventsModalWithTabs({
|
|
|
82
99
|
const router = useSafeRouter();
|
|
83
100
|
const containerRef = useSafeNavigationContainerRef();
|
|
84
101
|
const hasExpoRouter = isExpoRouterAvailable();
|
|
85
|
-
const [activeTab, setActiveTab] =
|
|
102
|
+
const [activeTab, setActiveTab] = usePersistedState(devToolsStorageKeys.routeEvents.activeTab(), "events", TAB_PERSISTENCE);
|
|
86
103
|
const [showUpgradeModal, setShowUpgradeModal] = useState(false);
|
|
87
104
|
// Serialized stack reported up by NavigationStack so the copy button can live
|
|
88
105
|
// in the shared navbar.
|
|
@@ -104,7 +121,7 @@ export function RouteEventsModalWithTabs({
|
|
|
104
121
|
// See the RouteTracker component export for easy setup.
|
|
105
122
|
|
|
106
123
|
// Local state to control subscription (true = subscribed, false = unsubscribed)
|
|
107
|
-
const [isListeningEnabled, setIsListeningEnabled] =
|
|
124
|
+
const [isListeningEnabled, setIsListeningEnabled] = usePersistedState(devToolsStorageKeys.routeEvents.isMonitoring(), true, BOOLEAN_PERSISTENCE);
|
|
108
125
|
|
|
109
126
|
// Event Listener state - using centralized store via hook
|
|
110
127
|
// Pass enabled option to control subscription
|
|
@@ -124,11 +141,8 @@ export function RouteEventsModalWithTabs({
|
|
|
124
141
|
const [selectedEvent, setSelectedEvent] = useState(null);
|
|
125
142
|
const [selectedVisitNumber, setSelectedVisitNumber] = useState(1);
|
|
126
143
|
const [searchQuery, setSearchQuery] = useState("");
|
|
127
|
-
const [ignoredPatterns, setIgnoredPatterns] =
|
|
144
|
+
const [ignoredPatterns, setIgnoredPatterns] = usePersistedState(devToolsStorageKeys.routeEvents.eventFilters(), new Set(["/_sitemap", "/api", "/__dev"]), STRING_SET_PERSISTENCE);
|
|
128
145
|
const lastEventRef = useRef(null);
|
|
129
|
-
const hasLoadedFilters = useRef(false);
|
|
130
|
-
const hasLoadedTabState = useRef(false);
|
|
131
|
-
const hasLoadedMonitoringState = useRef(false);
|
|
132
146
|
const handleModeChange = useCallback(_mode => {
|
|
133
147
|
// Mode changes handled by JsModal
|
|
134
148
|
}, []);
|
|
@@ -180,103 +194,6 @@ export function RouteEventsModalWithTabs({
|
|
|
180
194
|
}
|
|
181
195
|
}, [router, containerRef, hasExpoRouter, remote, isPro]);
|
|
182
196
|
|
|
183
|
-
// Load persisted tab state on mount
|
|
184
|
-
useEffect(() => {
|
|
185
|
-
if (!visible || hasLoadedTabState.current) return;
|
|
186
|
-
const loadTabState = async () => {
|
|
187
|
-
try {
|
|
188
|
-
const storedTab = await persistentStorage.getItem(devToolsStorageKeys.routeEvents.activeTab());
|
|
189
|
-
// Every tab the selector offers, including "stack": the save side has
|
|
190
|
-
// always written it, so leaving it off this list meant the Stack tab
|
|
191
|
-
// was persisted and then silently discarded on the next launch —
|
|
192
|
-
// you came back to Events having chosen otherwise.
|
|
193
|
-
if (storedTab === "routes" || storedTab === "events" || storedTab === "stack") {
|
|
194
|
-
setActiveTab(storedTab);
|
|
195
|
-
}
|
|
196
|
-
hasLoadedTabState.current = true;
|
|
197
|
-
} catch (error) {
|
|
198
|
-
// Failed to load tab state
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
loadTabState();
|
|
202
|
-
}, [visible]);
|
|
203
|
-
|
|
204
|
-
// Load persisted monitoring state on mount
|
|
205
|
-
useEffect(() => {
|
|
206
|
-
if (!visible || hasLoadedMonitoringState.current) return;
|
|
207
|
-
const loadMonitoringState = async () => {
|
|
208
|
-
try {
|
|
209
|
-
const storedMonitoring = await persistentStorage.getItem(devToolsStorageKeys.routeEvents.isMonitoring());
|
|
210
|
-
if (storedMonitoring !== null) {
|
|
211
|
-
const shouldMonitor = storedMonitoring === "true";
|
|
212
|
-
setIsListeningEnabled(shouldMonitor);
|
|
213
|
-
}
|
|
214
|
-
hasLoadedMonitoringState.current = true;
|
|
215
|
-
} catch (error) {
|
|
216
|
-
// Failed to load monitoring state
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
loadMonitoringState();
|
|
220
|
-
}, [visible]);
|
|
221
|
-
|
|
222
|
-
// Save tab state when it changes
|
|
223
|
-
useEffect(() => {
|
|
224
|
-
if (!hasLoadedTabState.current) return;
|
|
225
|
-
const saveTabState = async () => {
|
|
226
|
-
try {
|
|
227
|
-
await persistentStorage.setItem(devToolsStorageKeys.routeEvents.activeTab(), activeTab);
|
|
228
|
-
} catch (error) {
|
|
229
|
-
// Failed to save tab state
|
|
230
|
-
}
|
|
231
|
-
};
|
|
232
|
-
saveTabState();
|
|
233
|
-
}, [activeTab]);
|
|
234
|
-
|
|
235
|
-
// Save monitoring state when it changes
|
|
236
|
-
useEffect(() => {
|
|
237
|
-
if (!hasLoadedMonitoringState.current) return;
|
|
238
|
-
const saveMonitoringState = async () => {
|
|
239
|
-
try {
|
|
240
|
-
await persistentStorage.setItem(devToolsStorageKeys.routeEvents.isMonitoring(), isListening.toString());
|
|
241
|
-
} catch (error) {
|
|
242
|
-
// Failed to save monitoring state
|
|
243
|
-
}
|
|
244
|
-
};
|
|
245
|
-
saveMonitoringState();
|
|
246
|
-
}, [isListening]);
|
|
247
|
-
|
|
248
|
-
// Load persisted filters on mount
|
|
249
|
-
useEffect(() => {
|
|
250
|
-
if (!visible || hasLoadedFilters.current) return;
|
|
251
|
-
const loadFilters = async () => {
|
|
252
|
-
try {
|
|
253
|
-
const storedFilters = await persistentStorage.getItem(devToolsStorageKeys.routeEvents.eventFilters());
|
|
254
|
-
if (storedFilters) {
|
|
255
|
-
const filters = JSON.parse(storedFilters);
|
|
256
|
-
setIgnoredPatterns(new Set(filters));
|
|
257
|
-
}
|
|
258
|
-
hasLoadedFilters.current = true;
|
|
259
|
-
} catch (error) {
|
|
260
|
-
// Failed to load filters
|
|
261
|
-
}
|
|
262
|
-
};
|
|
263
|
-
loadFilters();
|
|
264
|
-
}, [visible]);
|
|
265
|
-
|
|
266
|
-
// Save filters when they change
|
|
267
|
-
useEffect(() => {
|
|
268
|
-
if (!hasLoadedFilters.current) return;
|
|
269
|
-
const saveFilters = async () => {
|
|
270
|
-
try {
|
|
271
|
-
const filters = Array.from(ignoredPatterns);
|
|
272
|
-
await persistentStorage.setItem(devToolsStorageKeys.routeEvents.eventFilters(), JSON.stringify(filters));
|
|
273
|
-
} catch (error) {
|
|
274
|
-
// Failed to save filters
|
|
275
|
-
}
|
|
276
|
-
};
|
|
277
|
-
saveFilters();
|
|
278
|
-
}, [ignoredPatterns]);
|
|
279
|
-
|
|
280
197
|
// Event listener is now managed by useRouteEvents hook
|
|
281
198
|
|
|
282
199
|
const handleToggleListening = useCallback(() => {
|
|
@@ -726,7 +643,7 @@ const styles = StyleSheet.create({
|
|
|
726
643
|
fontWeight: "600",
|
|
727
644
|
marginTop: 16,
|
|
728
645
|
marginBottom: 8,
|
|
729
|
-
fontFamily:
|
|
646
|
+
fontFamily: monoFont,
|
|
730
647
|
letterSpacing: 0.5,
|
|
731
648
|
textTransform: "uppercase"
|
|
732
649
|
},
|
|
@@ -734,7 +651,7 @@ const styles = StyleSheet.create({
|
|
|
734
651
|
color: night.color.textSecondary,
|
|
735
652
|
fontSize: 14,
|
|
736
653
|
textAlign: "center",
|
|
737
|
-
fontFamily:
|
|
654
|
+
fontFamily: monoFont
|
|
738
655
|
},
|
|
739
656
|
contentWrapper: {
|
|
740
657
|
flex: 1
|
|
@@ -749,7 +666,7 @@ const styles = StyleSheet.create({
|
|
|
749
666
|
statsText: {
|
|
750
667
|
fontSize: 11,
|
|
751
668
|
color: night.color.textSecondary,
|
|
752
|
-
fontFamily:
|
|
669
|
+
fontFamily: monoFont,
|
|
753
670
|
textAlign: "center"
|
|
754
671
|
},
|
|
755
672
|
statsWarning: {
|
|
@@ -779,7 +696,7 @@ const styles = StyleSheet.create({
|
|
|
779
696
|
fontSize: 12,
|
|
780
697
|
fontWeight: "600",
|
|
781
698
|
color: night.color.warning,
|
|
782
|
-
fontFamily:
|
|
699
|
+
fontFamily: monoFont
|
|
783
700
|
},
|
|
784
701
|
lockedEventsBannerSubtext: {
|
|
785
702
|
fontSize: 11,
|