react-native-debug-toolkit 3.3.4 → 3.5.0
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/README.md +48 -46
- package/README.zh-CN.md +48 -46
- package/android/src/main/java/com/reactnativedebugtoolkit/DebugToolkitDevConnectModule.java +0 -187
- package/bin/debug-toolkit.js +0 -16
- package/ios/DebugToolkitDevConnect.h +0 -12
- package/ios/DebugToolkitDevConnect.mm +0 -321
- package/lib/commonjs/constants/logLevels.js +19 -0
- package/lib/commonjs/constants/logLevels.js.map +1 -0
- package/lib/commonjs/core/initialize.js +36 -18
- package/lib/commonjs/core/initialize.js.map +1 -1
- package/lib/commonjs/features/console/ConsoleLogTab.js +4 -15
- package/lib/commonjs/features/console/ConsoleLogTab.js.map +1 -1
- package/lib/commonjs/features/console/index.js +15 -8
- package/lib/commonjs/features/console/index.js.map +1 -1
- package/lib/commonjs/features/devConnect/DevConnectTab.js +18 -470
- package/lib/commonjs/features/devConnect/DevConnectTab.js.map +1 -1
- package/lib/commonjs/features/devConnect/devConnectPreferences.js +0 -12
- package/lib/commonjs/features/devConnect/devConnectPreferences.js.map +1 -1
- package/lib/commonjs/features/devConnect/devConnectUtils.js +2 -57
- package/lib/commonjs/features/devConnect/devConnectUtils.js.map +1 -1
- package/lib/commonjs/features/devConnect/index.js +1 -23
- package/lib/commonjs/features/devConnect/index.js.map +1 -1
- package/lib/commonjs/features/devConnect/nativeDevConnect.js +1 -103
- package/lib/commonjs/features/devConnect/nativeDevConnect.js.map +1 -1
- package/lib/commonjs/features/network/NetworkLogTab.js +91 -93
- package/lib/commonjs/features/network/NetworkLogTab.js.map +1 -1
- package/lib/commonjs/features/network/index.js +7 -4
- package/lib/commonjs/features/network/index.js.map +1 -1
- package/lib/commonjs/features/sessionHistory/SessionHistoryTab.js +1044 -0
- package/lib/commonjs/features/sessionHistory/SessionHistoryTab.js.map +1 -0
- package/lib/commonjs/features/sessionHistory/index.js +103 -0
- package/lib/commonjs/features/sessionHistory/index.js.map +1 -0
- package/lib/commonjs/features/track/index.js +4 -3
- package/lib/commonjs/features/track/index.js.map +1 -1
- package/lib/commonjs/index.js +27 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/DebugView.js +3 -0
- package/lib/commonjs/ui/DebugView.js.map +1 -1
- package/lib/commonjs/ui/panel/DebugPanel.js +67 -34
- package/lib/commonjs/ui/panel/DebugPanel.js.map +1 -1
- package/lib/commonjs/ui/panel/FeatureIntroCard.js +131 -0
- package/lib/commonjs/ui/panel/FeatureIntroCard.js.map +1 -0
- package/lib/commonjs/ui/panel/FeatureRail.js +163 -0
- package/lib/commonjs/ui/panel/FeatureRail.js.map +1 -0
- package/lib/commonjs/ui/panel/FloatPanelView.js +169 -32
- package/lib/commonjs/ui/panel/FloatPanelView.js.map +1 -1
- package/lib/commonjs/ui/panel/buildFeatureSummary.js +207 -0
- package/lib/commonjs/ui/panel/buildFeatureSummary.js.map +1 -0
- package/lib/commonjs/ui/panel/filterFeatureSnapshot.js +43 -0
- package/lib/commonjs/ui/panel/filterFeatureSnapshot.js.map +1 -0
- package/lib/commonjs/ui/panel/tabPersistence.js +17 -0
- package/lib/commonjs/ui/panel/tabPersistence.js.map +1 -0
- package/lib/commonjs/ui/theme/colors.js +6 -0
- package/lib/commonjs/ui/theme/colors.js.map +1 -1
- package/lib/commonjs/utils/DaemonClient.js +30 -8
- package/lib/commonjs/utils/DaemonClient.js.map +1 -1
- package/lib/commonjs/utils/SessionManager.js +132 -0
- package/lib/commonjs/utils/SessionManager.js.map +1 -0
- package/lib/commonjs/utils/StorageAdapter.js +104 -0
- package/lib/commonjs/utils/StorageAdapter.js.map +1 -0
- package/lib/commonjs/utils/createChannelFeature.js +22 -5
- package/lib/commonjs/utils/createChannelFeature.js.map +1 -1
- package/lib/commonjs/utils/createDebugTab.js +21 -0
- package/lib/commonjs/utils/createDebugTab.js.map +1 -0
- package/lib/commonjs/utils/createPersistedObservableStore.js +14 -8
- package/lib/commonjs/utils/createPersistedObservableStore.js.map +1 -1
- package/lib/commonjs/utils/debugPreferences.js +28 -6
- package/lib/commonjs/utils/debugPreferences.js.map +1 -1
- package/lib/commonjs/utils/deviceReport.js +5 -1
- package/lib/commonjs/utils/deviceReport.js.map +1 -1
- package/lib/commonjs/utils/logRuntime.js +32 -0
- package/lib/commonjs/utils/logRuntime.js.map +1 -0
- package/lib/module/constants/logLevels.js +15 -0
- package/lib/module/constants/logLevels.js.map +1 -0
- package/lib/module/core/initialize.js +36 -18
- package/lib/module/core/initialize.js.map +1 -1
- package/lib/module/features/console/ConsoleLogTab.js +1 -12
- package/lib/module/features/console/ConsoleLogTab.js.map +1 -1
- package/lib/module/features/console/index.js +15 -8
- package/lib/module/features/console/index.js.map +1 -1
- package/lib/module/features/devConnect/DevConnectTab.js +21 -473
- package/lib/module/features/devConnect/DevConnectTab.js.map +1 -1
- package/lib/module/features/devConnect/devConnectPreferences.js +1 -12
- package/lib/module/features/devConnect/devConnectPreferences.js.map +1 -1
- package/lib/module/features/devConnect/devConnectUtils.js +1 -53
- package/lib/module/features/devConnect/devConnectUtils.js.map +1 -1
- package/lib/module/features/devConnect/index.js +5 -9
- package/lib/module/features/devConnect/index.js.map +1 -1
- package/lib/module/features/devConnect/nativeDevConnect.js +1 -100
- package/lib/module/features/devConnect/nativeDevConnect.js.map +1 -1
- package/lib/module/features/network/NetworkLogTab.js +91 -93
- package/lib/module/features/network/NetworkLogTab.js.map +1 -1
- package/lib/module/features/network/index.js +7 -4
- package/lib/module/features/network/index.js.map +1 -1
- package/lib/module/features/sessionHistory/SessionHistoryTab.js +1039 -0
- package/lib/module/features/sessionHistory/SessionHistoryTab.js.map +1 -0
- package/lib/module/features/sessionHistory/index.js +99 -0
- package/lib/module/features/sessionHistory/index.js.map +1 -0
- package/lib/module/features/track/index.js +4 -3
- package/lib/module/features/track/index.js.map +1 -1
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/DebugView.js +3 -0
- package/lib/module/ui/DebugView.js.map +1 -1
- package/lib/module/ui/panel/DebugPanel.js +67 -34
- package/lib/module/ui/panel/DebugPanel.js.map +1 -1
- package/lib/module/ui/panel/FeatureIntroCard.js +126 -0
- package/lib/module/ui/panel/FeatureIntroCard.js.map +1 -0
- package/lib/module/ui/panel/FeatureRail.js +158 -0
- package/lib/module/ui/panel/FeatureRail.js.map +1 -0
- package/lib/module/ui/panel/FloatPanelView.js +170 -33
- package/lib/module/ui/panel/FloatPanelView.js.map +1 -1
- package/lib/module/ui/panel/buildFeatureSummary.js +203 -0
- package/lib/module/ui/panel/buildFeatureSummary.js.map +1 -0
- package/lib/module/ui/panel/filterFeatureSnapshot.js +39 -0
- package/lib/module/ui/panel/filterFeatureSnapshot.js.map +1 -0
- package/lib/module/ui/panel/tabPersistence.js +13 -0
- package/lib/module/ui/panel/tabPersistence.js.map +1 -0
- package/lib/module/ui/theme/colors.js +6 -0
- package/lib/module/ui/theme/colors.js.map +1 -1
- package/lib/module/utils/DaemonClient.js +30 -8
- package/lib/module/utils/DaemonClient.js.map +1 -1
- package/lib/module/utils/SessionManager.js +127 -0
- package/lib/module/utils/SessionManager.js.map +1 -0
- package/lib/module/utils/StorageAdapter.js +96 -0
- package/lib/module/utils/StorageAdapter.js.map +1 -0
- package/lib/module/utils/createChannelFeature.js +22 -5
- package/lib/module/utils/createChannelFeature.js.map +1 -1
- package/lib/module/utils/createDebugTab.js +17 -0
- package/lib/module/utils/createDebugTab.js.map +1 -0
- package/lib/module/utils/createPersistedObservableStore.js +14 -8
- package/lib/module/utils/createPersistedObservableStore.js.map +1 -1
- package/lib/module/utils/debugPreferences.js +27 -6
- package/lib/module/utils/debugPreferences.js.map +1 -1
- package/lib/module/utils/deviceReport.js +4 -1
- package/lib/module/utils/deviceReport.js.map +1 -1
- package/lib/module/utils/logRuntime.js +26 -0
- package/lib/module/utils/logRuntime.js.map +1 -0
- package/lib/typescript/src/constants/logLevels.d.ts +3 -0
- package/lib/typescript/src/constants/logLevels.d.ts.map +1 -0
- package/lib/typescript/src/core/initialize.d.ts +6 -0
- package/lib/typescript/src/core/initialize.d.ts.map +1 -1
- package/lib/typescript/src/features/console/ConsoleLogTab.d.ts.map +1 -1
- package/lib/typescript/src/features/console/index.d.ts +2 -1
- package/lib/typescript/src/features/console/index.d.ts.map +1 -1
- package/lib/typescript/src/features/devConnect/DevConnectTab.d.ts.map +1 -1
- package/lib/typescript/src/features/devConnect/devConnectPreferences.d.ts +0 -2
- package/lib/typescript/src/features/devConnect/devConnectPreferences.d.ts.map +1 -1
- package/lib/typescript/src/features/devConnect/devConnectUtils.d.ts +0 -20
- package/lib/typescript/src/features/devConnect/devConnectUtils.d.ts.map +1 -1
- package/lib/typescript/src/features/devConnect/index.d.ts +2 -2
- package/lib/typescript/src/features/devConnect/index.d.ts.map +1 -1
- package/lib/typescript/src/features/devConnect/nativeDevConnect.d.ts +0 -25
- package/lib/typescript/src/features/devConnect/nativeDevConnect.d.ts.map +1 -1
- package/lib/typescript/src/features/devConnect/types.d.ts +1 -3
- package/lib/typescript/src/features/devConnect/types.d.ts.map +1 -1
- package/lib/typescript/src/features/network/NetworkLogTab.d.ts.map +1 -1
- package/lib/typescript/src/features/network/index.d.ts +2 -1
- package/lib/typescript/src/features/network/index.d.ts.map +1 -1
- package/lib/typescript/src/features/sessionHistory/SessionHistoryTab.d.ts +20 -0
- package/lib/typescript/src/features/sessionHistory/SessionHistoryTab.d.ts.map +1 -0
- package/lib/typescript/src/features/sessionHistory/index.d.ts +4 -0
- package/lib/typescript/src/features/sessionHistory/index.d.ts.map +1 -0
- package/lib/typescript/src/features/track/index.d.ts +2 -1
- package/lib/typescript/src/features/track/index.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +6 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/types/feature.d.ts +1 -1
- package/lib/typescript/src/types/feature.d.ts.map +1 -1
- package/lib/typescript/src/types/index.d.ts +2 -0
- package/lib/typescript/src/types/index.d.ts.map +1 -1
- package/lib/typescript/src/ui/DebugView.d.ts +4 -2
- package/lib/typescript/src/ui/DebugView.d.ts.map +1 -1
- package/lib/typescript/src/ui/panel/DebugPanel.d.ts +3 -1
- package/lib/typescript/src/ui/panel/DebugPanel.d.ts.map +1 -1
- package/lib/typescript/src/ui/panel/FeatureIntroCard.d.ts +11 -0
- package/lib/typescript/src/ui/panel/FeatureIntroCard.d.ts.map +1 -0
- package/lib/typescript/src/ui/panel/FeatureRail.d.ts +16 -0
- package/lib/typescript/src/ui/panel/FeatureRail.d.ts.map +1 -0
- package/lib/typescript/src/ui/panel/FloatPanelView.d.ts.map +1 -1
- package/lib/typescript/src/ui/panel/buildFeatureSummary.d.ts +13 -0
- package/lib/typescript/src/ui/panel/buildFeatureSummary.d.ts.map +1 -0
- package/lib/typescript/src/ui/panel/filterFeatureSnapshot.d.ts +3 -0
- package/lib/typescript/src/ui/panel/filterFeatureSnapshot.d.ts.map +1 -0
- package/lib/typescript/src/ui/panel/tabPersistence.d.ts +3 -0
- package/lib/typescript/src/ui/panel/tabPersistence.d.ts.map +1 -0
- package/lib/typescript/src/ui/theme/colors.d.ts +5 -0
- package/lib/typescript/src/ui/theme/colors.d.ts.map +1 -1
- package/lib/typescript/src/utils/DaemonClient.d.ts +7 -1
- package/lib/typescript/src/utils/DaemonClient.d.ts.map +1 -1
- package/lib/typescript/src/utils/SessionManager.d.ts +30 -0
- package/lib/typescript/src/utils/SessionManager.d.ts.map +1 -0
- package/lib/typescript/src/utils/StorageAdapter.d.ts +38 -0
- package/lib/typescript/src/utils/StorageAdapter.d.ts.map +1 -0
- package/lib/typescript/src/utils/createChannelFeature.d.ts +2 -0
- package/lib/typescript/src/utils/createChannelFeature.d.ts.map +1 -1
- package/lib/typescript/src/utils/createDebugTab.d.ts +18 -0
- package/lib/typescript/src/utils/createDebugTab.d.ts.map +1 -0
- package/lib/typescript/src/utils/createPersistedObservableStore.d.ts +4 -1
- package/lib/typescript/src/utils/createPersistedObservableStore.d.ts.map +1 -1
- package/lib/typescript/src/utils/debugPreferences.d.ts +1 -4
- package/lib/typescript/src/utils/debugPreferences.d.ts.map +1 -1
- package/lib/typescript/src/utils/deviceReport.d.ts +1 -0
- package/lib/typescript/src/utils/deviceReport.d.ts.map +1 -1
- package/lib/typescript/src/utils/logRuntime.d.ts +13 -0
- package/lib/typescript/src/utils/logRuntime.d.ts.map +1 -0
- package/package.json +10 -6
- package/src/constants/logLevels.ts +13 -0
- package/src/core/initialize.ts +61 -21
- package/src/features/console/ConsoleLogTab.tsx +1 -14
- package/src/features/console/index.ts +18 -8
- package/src/features/devConnect/DevConnectTab.tsx +17 -381
- package/src/features/devConnect/devConnectPreferences.ts +0 -15
- package/src/features/devConnect/devConnectUtils.ts +1 -81
- package/src/features/devConnect/index.ts +2 -9
- package/src/features/devConnect/nativeDevConnect.ts +1 -136
- package/src/features/devConnect/types.ts +1 -3
- package/src/features/network/NetworkLogTab.tsx +61 -71
- package/src/features/network/index.ts +12 -3
- package/src/features/sessionHistory/SessionHistoryTab.tsx +691 -0
- package/src/features/sessionHistory/index.ts +102 -0
- package/src/features/track/index.ts +10 -3
- package/src/index.ts +13 -0
- package/src/types/feature.ts +2 -1
- package/src/types/index.ts +10 -0
- package/src/ui/DebugView.tsx +6 -1
- package/src/ui/panel/DebugPanel.tsx +60 -30
- package/src/ui/panel/FeatureIntroCard.tsx +127 -0
- package/src/ui/panel/FeatureRail.tsx +165 -0
- package/src/ui/panel/FloatPanelView.tsx +176 -25
- package/src/ui/panel/buildFeatureSummary.ts +288 -0
- package/src/ui/panel/filterFeatureSnapshot.ts +51 -0
- package/src/ui/panel/tabPersistence.ts +22 -0
- package/src/ui/theme/colors.ts +7 -0
- package/src/utils/DaemonClient.ts +33 -5
- package/src/utils/SessionManager.ts +174 -0
- package/src/utils/StorageAdapter.ts +135 -0
- package/src/utils/createChannelFeature.ts +28 -6
- package/src/utils/createDebugTab.ts +32 -0
- package/src/utils/createPersistedObservableStore.ts +18 -10
- package/src/utils/debugPreferences.ts +38 -8
- package/src/utils/deviceReport.ts +5 -1
- package/src/utils/logRuntime.ts +39 -0
- package/app.plugin.js +0 -51
- package/dev-client.js +0 -3
- package/lib/commonjs/ui/panel/FeatureTabBar.js +0 -182
- package/lib/commonjs/ui/panel/FeatureTabBar.js.map +0 -1
- package/lib/module/ui/panel/FeatureTabBar.js +0 -177
- package/lib/module/ui/panel/FeatureTabBar.js.map +0 -1
- package/lib/typescript/src/ui/panel/FeatureTabBar.d.ts +0 -13
- package/lib/typescript/src/ui/panel/FeatureTabBar.d.ts.map +0 -1
- package/scripts/bundle/android.js +0 -101
- package/scripts/bundle/cli.js +0 -57
- package/scripts/bundle/doctor.js +0 -38
- package/scripts/bundle/ios.js +0 -179
- package/scripts/bundle/setup.js +0 -39
- package/scripts/debug-bundle.gradle +0 -147
- package/src/ui/panel/FeatureTabBar.tsx +0 -204
|
@@ -2,15 +2,21 @@ import React, { Component, useCallback, useEffect, useRef, useState } from 'reac
|
|
|
2
2
|
import {
|
|
3
3
|
View,
|
|
4
4
|
Text,
|
|
5
|
+
TextInput,
|
|
5
6
|
StyleSheet,
|
|
6
7
|
Animated,
|
|
7
8
|
} from 'react-native';
|
|
8
9
|
import type { AnyDebugFeature } from '../../types';
|
|
10
|
+
import { Colors } from '../theme/colors';
|
|
9
11
|
import { getPreference, setPreference, KEYS } from '../../utils/debugPreferences';
|
|
10
12
|
import { FloatIcon } from '../floating/FloatIcon';
|
|
11
13
|
import { DebugPanel } from './DebugPanel';
|
|
12
|
-
import {
|
|
13
|
-
import type {
|
|
14
|
+
import { FeatureRail } from './FeatureRail';
|
|
15
|
+
import type { RailItem } from './FeatureRail';
|
|
16
|
+
import { FeatureIntroCard } from './FeatureIntroCard';
|
|
17
|
+
import { buildFeatureSummary } from './buildFeatureSummary';
|
|
18
|
+
import { filterFeatureSnapshot } from './filterFeatureSnapshot';
|
|
19
|
+
import { resolveStoredTabIndex } from './tabPersistence';
|
|
14
20
|
import { useTabAnimation } from './useTabAnimation';
|
|
15
21
|
|
|
16
22
|
// ─── Error Boundary ────────────────────────────────────
|
|
@@ -39,6 +45,57 @@ class DebugErrorBoundary extends Component<
|
|
|
39
45
|
}
|
|
40
46
|
}
|
|
41
47
|
|
|
48
|
+
// ─── Snapshot helpers ──────────────────────────────────
|
|
49
|
+
|
|
50
|
+
function snapshotCount(feature: AnyDebugFeature): number | undefined {
|
|
51
|
+
try {
|
|
52
|
+
const snap = feature.getSnapshot();
|
|
53
|
+
if (Array.isArray(snap)) return snap.length;
|
|
54
|
+
if (snap && typeof snap === 'object') {
|
|
55
|
+
const obj = snap as Record<string, unknown>;
|
|
56
|
+
if (Array.isArray(obj.items)) return obj.items.length;
|
|
57
|
+
if (Array.isArray(obj.logs)) return obj.logs.length;
|
|
58
|
+
if (Array.isArray(obj.entries)) return obj.entries.length;
|
|
59
|
+
if (Array.isArray(obj.environments)) return obj.environments.length;
|
|
60
|
+
}
|
|
61
|
+
} catch { /* ignore */ }
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
interface PanelConnectionStatus {
|
|
66
|
+
label: string;
|
|
67
|
+
color: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
interface DevConnectSnapshot {
|
|
71
|
+
isSimulator?: boolean;
|
|
72
|
+
computerHost?: string;
|
|
73
|
+
daemonPort?: string;
|
|
74
|
+
streaming?: boolean;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function buildPanelConnectionStatus(features: AnyDebugFeature[]): PanelConnectionStatus {
|
|
78
|
+
const devConnect = features.find((f) => f.name === 'devConnect');
|
|
79
|
+
if (!devConnect) {
|
|
80
|
+
return { label: 'offline desktop sync unavailable', color: Colors.textLight };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
const snap = (devConnect.getSnapshot() ?? {}) as DevConnectSnapshot;
|
|
85
|
+
const host = snap.isSimulator ? 'localhost' : snap.computerHost?.trim();
|
|
86
|
+
const port = snap.daemonPort?.trim();
|
|
87
|
+
const target = host && port ? `${host}:${port}` : host || (port ? `port ${port}` : 'not configured');
|
|
88
|
+
return {
|
|
89
|
+
label: `${snap.streaming ? 'live' : 'offline'} ${target}`,
|
|
90
|
+
color: snap.streaming ? Colors.success : Colors.textLight,
|
|
91
|
+
};
|
|
92
|
+
} catch {
|
|
93
|
+
return { label: 'offline desktop sync unavailable', color: Colors.textLight };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ─── Main Component ────────────────────────────────────
|
|
98
|
+
|
|
42
99
|
interface FloatPanelViewProps {
|
|
43
100
|
features: AnyDebugFeature[];
|
|
44
101
|
panelOpen: boolean;
|
|
@@ -49,29 +106,40 @@ interface FloatPanelViewProps {
|
|
|
49
106
|
|
|
50
107
|
export function FloatPanelView({ features, panelOpen, onOpenPanel, onClosePanel, onClearAll }: FloatPanelViewProps) {
|
|
51
108
|
const [activeTab, setActiveTab] = useState(0);
|
|
109
|
+
const [searchQuery, setSearchQuery] = useState('');
|
|
110
|
+
const [filterBad, setFilterBad] = useState(false);
|
|
52
111
|
const tabLoaded = useRef(false);
|
|
53
112
|
|
|
54
113
|
// Restore last tab on mount
|
|
55
114
|
useEffect(() => {
|
|
115
|
+
if (tabLoaded.current || features.length === 0) return;
|
|
56
116
|
let mounted = true;
|
|
57
117
|
getPreference(KEYS.lastTab).then((val) => {
|
|
58
|
-
if (!mounted ||
|
|
59
|
-
const idx =
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
118
|
+
if (!mounted || tabLoaded.current) return;
|
|
119
|
+
const idx = resolveStoredTabIndex(features, val);
|
|
120
|
+
setActiveTab(idx);
|
|
121
|
+
const featureName = features[idx]?.name;
|
|
122
|
+
if (featureName && featureName !== val) {
|
|
123
|
+
setPreference(KEYS.lastTab, featureName);
|
|
63
124
|
}
|
|
125
|
+
tabLoaded.current = true;
|
|
64
126
|
});
|
|
65
127
|
return () => { mounted = false; };
|
|
66
|
-
}, []);
|
|
128
|
+
}, [features]);
|
|
67
129
|
|
|
68
130
|
const { contentOpacity, contentTranslateX, panHandlers, switchTab } = useTabAnimation({
|
|
69
131
|
activeTab,
|
|
70
132
|
tabCount: features.length,
|
|
71
133
|
onTabChange: useCallback((index: number) => {
|
|
134
|
+
tabLoaded.current = true;
|
|
135
|
+
setSearchQuery('');
|
|
136
|
+
setFilterBad(false);
|
|
72
137
|
setActiveTab(index);
|
|
73
|
-
|
|
74
|
-
|
|
138
|
+
const featureName = features[index]?.name;
|
|
139
|
+
if (featureName) {
|
|
140
|
+
setPreference(KEYS.lastTab, featureName);
|
|
141
|
+
}
|
|
142
|
+
}, [features]),
|
|
75
143
|
});
|
|
76
144
|
|
|
77
145
|
// Feature subscription → re-render on data changes
|
|
@@ -96,14 +164,41 @@ export function FloatPanelView({ features, panelOpen, onOpenPanel, onClosePanel,
|
|
|
96
164
|
// Clamp activeTab if features shrink
|
|
97
165
|
useEffect(() => {
|
|
98
166
|
if (features.length > 0 && activeTab >= features.length) {
|
|
167
|
+
tabLoaded.current = true;
|
|
99
168
|
setActiveTab(0);
|
|
100
|
-
|
|
169
|
+
const featureName = features[0]?.name;
|
|
170
|
+
if (featureName) {
|
|
171
|
+
setPreference(KEYS.lastTab, featureName);
|
|
172
|
+
}
|
|
101
173
|
}
|
|
102
|
-
}, [features
|
|
174
|
+
}, [features, activeTab]);
|
|
103
175
|
|
|
104
176
|
// Badge (first feature that returns one)
|
|
105
177
|
const envBadge = features.map((f) => f.badge?.()).find((b) => b != null) ?? null;
|
|
106
|
-
|
|
178
|
+
|
|
179
|
+
// Rail items with counts
|
|
180
|
+
const railItems: RailItem[] = features.map((f) => {
|
|
181
|
+
const b = f.badge?.();
|
|
182
|
+
return { id: f.name, label: f.label, dotColor: b?.color ?? null, count: snapshotCount(f) };
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
const panelConnectionStatus = buildPanelConnectionStatus(features);
|
|
186
|
+
|
|
187
|
+
const handleClearAll = useCallback(() => {
|
|
188
|
+
setSearchQuery('');
|
|
189
|
+
setFilterBad(false);
|
|
190
|
+
onClearAll();
|
|
191
|
+
}, [onClearAll]);
|
|
192
|
+
|
|
193
|
+
// Active feature + summary
|
|
194
|
+
const activeFeature = features[activeTab];
|
|
195
|
+
const activeSnapshot = activeFeature?.getSnapshot();
|
|
196
|
+
const activeSummary = activeFeature ? buildFeatureSummary(activeFeature, activeSnapshot) : null;
|
|
197
|
+
|
|
198
|
+
// Filtered snapshot — reuse activeSnapshot to avoid double getSnapshot()
|
|
199
|
+
const filteredSnapshot = activeFeature
|
|
200
|
+
? filterFeatureSnapshot(activeFeature, activeSnapshot, searchQuery, filterBad ? 'bad' : 'all')
|
|
201
|
+
: null;
|
|
107
202
|
|
|
108
203
|
// Render active feature content
|
|
109
204
|
const renderFeatureContent = () => {
|
|
@@ -112,7 +207,7 @@ export function FloatPanelView({ features, panelOpen, onOpenPanel, onClosePanel,
|
|
|
112
207
|
}
|
|
113
208
|
const feature = features[activeTab];
|
|
114
209
|
if (!feature) return <Text style={styles.emptyText}>Feature not found</Text>;
|
|
115
|
-
const snapshot =
|
|
210
|
+
const snapshot = filteredSnapshot;
|
|
116
211
|
const TabComponent = feature.renderContent;
|
|
117
212
|
if (TabComponent) return <TabComponent snapshot={snapshot} feature={feature} />;
|
|
118
213
|
return (
|
|
@@ -122,6 +217,8 @@ export function FloatPanelView({ features, panelOpen, onOpenPanel, onClosePanel,
|
|
|
122
217
|
);
|
|
123
218
|
};
|
|
124
219
|
|
|
220
|
+
const showSearch = activeSummary ? (activeSummary.count != null && activeSummary.count > 0) : false;
|
|
221
|
+
|
|
125
222
|
return (
|
|
126
223
|
<DebugErrorBoundary onError={onClosePanel}>
|
|
127
224
|
<View style={styles.container} pointerEvents="box-none">
|
|
@@ -129,18 +226,44 @@ export function FloatPanelView({ features, panelOpen, onOpenPanel, onClosePanel,
|
|
|
129
226
|
{panelOpen && (
|
|
130
227
|
<DebugPanel
|
|
131
228
|
onClose={onClosePanel}
|
|
132
|
-
onClearAll={
|
|
229
|
+
onClearAll={handleClearAll}
|
|
230
|
+
syncLabel={panelConnectionStatus.label}
|
|
231
|
+
syncColor={panelConnectionStatus.color}
|
|
133
232
|
>
|
|
134
|
-
<
|
|
135
|
-
|
|
136
|
-
style={
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
233
|
+
<View style={styles.bodyRow}>
|
|
234
|
+
<FeatureRail items={railItems} activeIndex={activeTab} onSelectTab={switchTab} />
|
|
235
|
+
<View style={styles.contentColumn}>
|
|
236
|
+
{activeFeature && activeSummary && (
|
|
237
|
+
<FeatureIntroCard
|
|
238
|
+
title={activeFeature.label}
|
|
239
|
+
summary={activeSummary}
|
|
240
|
+
filterBad={filterBad}
|
|
241
|
+
onFilterBad={setFilterBad}
|
|
242
|
+
/>
|
|
243
|
+
)}
|
|
244
|
+
{showSearch && (
|
|
245
|
+
<View style={styles.toolbar}>
|
|
246
|
+
<TextInput
|
|
247
|
+
style={styles.searchInput}
|
|
248
|
+
placeholder="Search..."
|
|
249
|
+
placeholderTextColor={Colors.textLight}
|
|
250
|
+
value={searchQuery}
|
|
251
|
+
onChangeText={setSearchQuery}
|
|
252
|
+
returnKeyType="search"
|
|
253
|
+
/>
|
|
254
|
+
</View>
|
|
255
|
+
)}
|
|
256
|
+
<Animated.View
|
|
257
|
+
style={[
|
|
258
|
+
styles.contentContainer,
|
|
259
|
+
{ opacity: contentOpacity, transform: [{ translateX: contentTranslateX }] },
|
|
260
|
+
]}
|
|
261
|
+
{...panHandlers}
|
|
262
|
+
>
|
|
263
|
+
{renderFeatureContent()}
|
|
264
|
+
</Animated.View>
|
|
265
|
+
</View>
|
|
266
|
+
</View>
|
|
144
267
|
</DebugPanel>
|
|
145
268
|
)}
|
|
146
269
|
</View>
|
|
@@ -157,6 +280,34 @@ const styles = StyleSheet.create({
|
|
|
157
280
|
bottom: 0,
|
|
158
281
|
zIndex: 999,
|
|
159
282
|
},
|
|
283
|
+
bodyRow: {
|
|
284
|
+
flex: 1,
|
|
285
|
+
flexDirection: 'row',
|
|
286
|
+
},
|
|
287
|
+
contentColumn: {
|
|
288
|
+
flex: 1,
|
|
289
|
+
},
|
|
290
|
+
toolbar: {
|
|
291
|
+
flexDirection: 'row',
|
|
292
|
+
alignItems: 'center',
|
|
293
|
+
gap: 8,
|
|
294
|
+
paddingHorizontal: 10,
|
|
295
|
+
paddingVertical: 8,
|
|
296
|
+
borderBottomWidth: StyleSheet.hairlineWidth,
|
|
297
|
+
borderBottomColor: Colors.border,
|
|
298
|
+
backgroundColor: Colors.background,
|
|
299
|
+
},
|
|
300
|
+
searchInput: {
|
|
301
|
+
flex: 1,
|
|
302
|
+
height: 34,
|
|
303
|
+
borderWidth: 1,
|
|
304
|
+
borderColor: Colors.border,
|
|
305
|
+
borderRadius: 8,
|
|
306
|
+
backgroundColor: Colors.surface,
|
|
307
|
+
paddingHorizontal: 10,
|
|
308
|
+
fontSize: 13,
|
|
309
|
+
color: Colors.text,
|
|
310
|
+
},
|
|
160
311
|
contentContainer: { flex: 1 },
|
|
161
312
|
emptyText: {
|
|
162
313
|
padding: 20,
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import type { AnyDebugFeature } from '../../types';
|
|
2
|
+
|
|
3
|
+
export interface FeatureSummary {
|
|
4
|
+
capabilityText: string;
|
|
5
|
+
count?: number;
|
|
6
|
+
badCount?: number;
|
|
7
|
+
latestLabel?: string;
|
|
8
|
+
statusLabel?: string;
|
|
9
|
+
statusColor?: string;
|
|
10
|
+
filterMode?: 'all' | 'bad';
|
|
11
|
+
supportsBadFilter: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function buildFeatureSummary(
|
|
15
|
+
feature: AnyDebugFeature,
|
|
16
|
+
snapshot: unknown,
|
|
17
|
+
): FeatureSummary {
|
|
18
|
+
const name = feature.name;
|
|
19
|
+
|
|
20
|
+
if (name === 'network') return buildNetworkSummary(snapshot);
|
|
21
|
+
if (name === 'console') return buildConsoleSummary(snapshot);
|
|
22
|
+
if (name === 'navigation') return buildNavigationSummary(snapshot);
|
|
23
|
+
if (name === 'zustand') return buildZustandSummary(snapshot);
|
|
24
|
+
if (name === 'track') return buildTrackSummary(snapshot);
|
|
25
|
+
if (name === 'clipboard') return buildClipboardSummary(snapshot);
|
|
26
|
+
if (name === 'environment') return buildEnvironmentSummary(snapshot);
|
|
27
|
+
if (name === 'devConnect') return buildDevConnectSummary(snapshot);
|
|
28
|
+
if (name === 'sessionHistory') return buildSessionHistorySummary(snapshot);
|
|
29
|
+
if (name === 'thirdPartyLibs') return buildThirdPartyLibsSummary(snapshot);
|
|
30
|
+
if (name === 'native') return buildNativeSummary(snapshot);
|
|
31
|
+
|
|
32
|
+
return buildUnknownSummary(snapshot);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ─── Per-feature builders ──────────────────────────────
|
|
36
|
+
|
|
37
|
+
interface NetworkItem {
|
|
38
|
+
request?: { method?: string; url?: string };
|
|
39
|
+
response?: { status?: number };
|
|
40
|
+
error?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function buildNetworkSummary(snapshot: unknown): FeatureSummary {
|
|
44
|
+
const items = asArray(snapshot);
|
|
45
|
+
const count = items.length;
|
|
46
|
+
let badCount = 0;
|
|
47
|
+
let latestLabel: string | undefined;
|
|
48
|
+
|
|
49
|
+
if (count > 0) {
|
|
50
|
+
for (const item of items) {
|
|
51
|
+
const n = item as NetworkItem;
|
|
52
|
+
if (n.error || (n.response?.status ?? 0) >= 400) badCount++;
|
|
53
|
+
}
|
|
54
|
+
const last = items[items.length - 1] as NetworkItem;
|
|
55
|
+
const method = last.request?.method?.toUpperCase() ?? '';
|
|
56
|
+
const url = last.request?.url ?? '';
|
|
57
|
+
const status = last.response?.status;
|
|
58
|
+
const path = extractPath(url);
|
|
59
|
+
latestLabel = [method, path, status].filter(Boolean).join(' ');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
capabilityText: 'HTTP capture, status, duration, request and response body',
|
|
64
|
+
count,
|
|
65
|
+
badCount: badCount > 0 ? badCount : undefined,
|
|
66
|
+
latestLabel,
|
|
67
|
+
supportsBadFilter: count > 0,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
interface ConsoleItem {
|
|
72
|
+
level?: string;
|
|
73
|
+
data?: unknown[];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function buildConsoleSummary(snapshot: unknown): FeatureSummary {
|
|
77
|
+
const items = asArray(snapshot);
|
|
78
|
+
const count = items.length;
|
|
79
|
+
let badCount = 0;
|
|
80
|
+
let latestLabel: string | undefined;
|
|
81
|
+
|
|
82
|
+
if (count > 0) {
|
|
83
|
+
for (const item of items) {
|
|
84
|
+
const lvl = (item as ConsoleItem).level ?? '';
|
|
85
|
+
if (lvl === 'warn' || lvl === 'error' || lvl === 'fatal') badCount++;
|
|
86
|
+
}
|
|
87
|
+
const last = items[items.length - 1] as ConsoleItem;
|
|
88
|
+
latestLabel = formatConsoleMessage(last.data);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
capabilityText: 'Console log capture with level filtering',
|
|
93
|
+
count,
|
|
94
|
+
badCount: badCount > 0 ? badCount : undefined,
|
|
95
|
+
latestLabel,
|
|
96
|
+
supportsBadFilter: count > 0,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
interface NavigationItem {
|
|
101
|
+
from?: string;
|
|
102
|
+
to?: string;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function buildNavigationSummary(snapshot: unknown): FeatureSummary {
|
|
106
|
+
const items = asArray(snapshot);
|
|
107
|
+
const count = items.length;
|
|
108
|
+
let latestLabel: string | undefined;
|
|
109
|
+
|
|
110
|
+
if (count > 0) {
|
|
111
|
+
const last = items[items.length - 1] as NavigationItem;
|
|
112
|
+
const from = last.from ?? '?';
|
|
113
|
+
const to = last.to ?? '?';
|
|
114
|
+
latestLabel = `${from} → ${to}`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
capabilityText: 'Screen navigation tracking with route history',
|
|
119
|
+
count,
|
|
120
|
+
latestLabel,
|
|
121
|
+
supportsBadFilter: false,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
interface ZustandItem {
|
|
126
|
+
action?: string;
|
|
127
|
+
storeName?: string;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function buildZustandSummary(snapshot: unknown): FeatureSummary {
|
|
131
|
+
const items = asArray(snapshot);
|
|
132
|
+
const count = items.length;
|
|
133
|
+
let latestLabel: string | undefined;
|
|
134
|
+
|
|
135
|
+
if (count > 0) {
|
|
136
|
+
const last = items[items.length - 1] as ZustandItem;
|
|
137
|
+
const parts = [last.action, last.storeName].filter(Boolean);
|
|
138
|
+
latestLabel = parts.join(' @ ') || undefined;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
capabilityText: 'State change tracking for Zustand stores',
|
|
143
|
+
count,
|
|
144
|
+
latestLabel,
|
|
145
|
+
supportsBadFilter: false,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
interface TrackItem {
|
|
150
|
+
eventName?: string;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function buildTrackSummary(snapshot: unknown): FeatureSummary {
|
|
154
|
+
const items = asArray(snapshot);
|
|
155
|
+
const count = items.length;
|
|
156
|
+
let latestLabel: string | undefined;
|
|
157
|
+
|
|
158
|
+
if (count > 0) {
|
|
159
|
+
const last = items[items.length - 1] as TrackItem;
|
|
160
|
+
latestLabel = last.eventName;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
capabilityText: 'Analytics event tracking and inspection',
|
|
165
|
+
count,
|
|
166
|
+
latestLabel,
|
|
167
|
+
supportsBadFilter: false,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function buildClipboardSummary(_snapshot: unknown): FeatureSummary {
|
|
172
|
+
return {
|
|
173
|
+
capabilityText: 'Clipboard event monitoring',
|
|
174
|
+
supportsBadFilter: false,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
interface EnvironmentSnap {
|
|
179
|
+
environments?: Array<{ id: string; label: string }>;
|
|
180
|
+
currentEnvironmentId?: string | null;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function buildEnvironmentSummary(snapshot: unknown): FeatureSummary {
|
|
184
|
+
const env = (snapshot ?? {}) as EnvironmentSnap;
|
|
185
|
+
const envs = env.environments ?? [];
|
|
186
|
+
const current = envs.find((e) => e.id === env.currentEnvironmentId);
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
capabilityText: 'Environment configuration and switching',
|
|
190
|
+
count: envs.length || undefined,
|
|
191
|
+
latestLabel: current?.label,
|
|
192
|
+
statusLabel: current?.label,
|
|
193
|
+
supportsBadFilter: false,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
interface DevConnectSnap {
|
|
198
|
+
streaming?: boolean;
|
|
199
|
+
computerHost?: string;
|
|
200
|
+
daemonPort?: string;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function buildDevConnectSummary(snapshot: unknown): FeatureSummary {
|
|
204
|
+
const s = (snapshot ?? {}) as DevConnectSnap;
|
|
205
|
+
const host = [s.computerHost, s.daemonPort].filter(Boolean).join(':');
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
capabilityText: 'Desktop sync with daemon connection',
|
|
209
|
+
statusLabel: host ? `${s.streaming ? 'live' : 'offline'} ${host}` : s.streaming ? 'live' : undefined,
|
|
210
|
+
statusColor: s.streaming ? '#34C759' : undefined,
|
|
211
|
+
supportsBadFilter: false,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
interface SessionHistorySnap {
|
|
216
|
+
sessions?: unknown[];
|
|
217
|
+
currentSessionId?: string;
|
|
218
|
+
logCounts?: Record<string, unknown>;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function buildSessionHistorySummary(snapshot: unknown): FeatureSummary {
|
|
222
|
+
const s = (snapshot ?? {}) as SessionHistorySnap;
|
|
223
|
+
const count = s.sessions?.length;
|
|
224
|
+
return {
|
|
225
|
+
capabilityText: 'Session log recording and replay',
|
|
226
|
+
count: count || undefined,
|
|
227
|
+
latestLabel: s.currentSessionId,
|
|
228
|
+
supportsBadFilter: false,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function buildThirdPartyLibsSummary(snapshot: unknown): FeatureSummary {
|
|
233
|
+
const items = asArray(snapshot);
|
|
234
|
+
return {
|
|
235
|
+
capabilityText: 'Third-party library inspection and management',
|
|
236
|
+
count: items.length || undefined,
|
|
237
|
+
supportsBadFilter: false,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function buildNativeSummary(snapshot: unknown): FeatureSummary {
|
|
242
|
+
const items = asArray(snapshot);
|
|
243
|
+
let badCount = 0;
|
|
244
|
+
for (const item of items) {
|
|
245
|
+
const lvl = (item as { level?: string }).level ?? '';
|
|
246
|
+
if (lvl === 'warn' || lvl === 'error' || lvl === 'fatal') badCount++;
|
|
247
|
+
}
|
|
248
|
+
return {
|
|
249
|
+
capabilityText: 'Native log capture',
|
|
250
|
+
count: items.length || undefined,
|
|
251
|
+
badCount: badCount > 0 ? badCount : undefined,
|
|
252
|
+
supportsBadFilter: items.length > 0,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function buildUnknownSummary(snapshot: unknown): FeatureSummary {
|
|
257
|
+
const items = asArray(snapshot);
|
|
258
|
+
return {
|
|
259
|
+
capabilityText: `${items.length} item${items.length !== 1 ? 's' : ''} captured`,
|
|
260
|
+
count: items.length || undefined,
|
|
261
|
+
supportsBadFilter: false,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// ─── Helpers ───────────────────────────────────────────
|
|
266
|
+
|
|
267
|
+
function asArray(snap: unknown): unknown[] {
|
|
268
|
+
if (Array.isArray(snap)) return snap;
|
|
269
|
+
return [];
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function extractPath(url: string): string {
|
|
273
|
+
try {
|
|
274
|
+
const u = new URL(url);
|
|
275
|
+
return u.pathname + u.search;
|
|
276
|
+
} catch {
|
|
277
|
+
return url;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function formatConsoleMessage(data: unknown[] | undefined): string | undefined {
|
|
282
|
+
if (!data || data.length === 0) return undefined;
|
|
283
|
+
const joined = data
|
|
284
|
+
.map((d) => (typeof d === 'string' ? d : JSON.stringify(d)))
|
|
285
|
+
.join(' ')
|
|
286
|
+
.slice(0, 60);
|
|
287
|
+
return joined || undefined;
|
|
288
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { AnyDebugFeature } from '../../types';
|
|
2
|
+
|
|
3
|
+
export function filterFeatureSnapshot(
|
|
4
|
+
feature: AnyDebugFeature,
|
|
5
|
+
snapshot: unknown,
|
|
6
|
+
query: string,
|
|
7
|
+
filterMode: 'all' | 'bad',
|
|
8
|
+
): unknown {
|
|
9
|
+
if (!Array.isArray(snapshot)) return snapshot;
|
|
10
|
+
|
|
11
|
+
const name = feature.name;
|
|
12
|
+
const supportsBad =
|
|
13
|
+
name === 'network' || name === 'console' || name === 'native';
|
|
14
|
+
|
|
15
|
+
return (snapshot as unknown[]).filter((item) => {
|
|
16
|
+
if (filterMode === 'bad' && supportsBad) {
|
|
17
|
+
if (!isBad(name, item as Record<string, unknown>)) return false;
|
|
18
|
+
}
|
|
19
|
+
if (query) {
|
|
20
|
+
const hay = extractSearchableText(item).toLowerCase();
|
|
21
|
+
if (!hay.includes(query.toLowerCase())) return false;
|
|
22
|
+
}
|
|
23
|
+
return true;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function isBad(
|
|
28
|
+
featureName: string,
|
|
29
|
+
item: Record<string, unknown>,
|
|
30
|
+
): boolean {
|
|
31
|
+
if (featureName === 'network') {
|
|
32
|
+
const resp = item.response as Record<string, unknown> | undefined;
|
|
33
|
+
return !!(item.error || ((resp?.status as number) ?? 0) >= 400);
|
|
34
|
+
}
|
|
35
|
+
// console, native
|
|
36
|
+
const lvl = (item.level as string) ?? '';
|
|
37
|
+
return lvl === 'warn' || lvl === 'error' || lvl === 'fatal';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function extractSearchableText(item: unknown): string {
|
|
41
|
+
if (item == null) return '';
|
|
42
|
+
if (typeof item === 'string') return item;
|
|
43
|
+
if (typeof item === 'number' || typeof item === 'boolean') return String(item);
|
|
44
|
+
if (Array.isArray(item)) return item.map(extractSearchableText).join(' ');
|
|
45
|
+
const parts: string[] = [];
|
|
46
|
+
for (const val of Object.values(item as Record<string, unknown>)) {
|
|
47
|
+
const t = extractSearchableText(val);
|
|
48
|
+
if (t) parts.push(t);
|
|
49
|
+
}
|
|
50
|
+
return parts.join(' ');
|
|
51
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AnyDebugFeature } from '../../types';
|
|
2
|
+
|
|
3
|
+
export function resolveStoredTabIndex(
|
|
4
|
+
features: AnyDebugFeature[],
|
|
5
|
+
storedTab: string | null,
|
|
6
|
+
): number {
|
|
7
|
+
if (!storedTab) return 0;
|
|
8
|
+
|
|
9
|
+
const nameIndex = features.findIndex((feature) => feature.name === storedTab);
|
|
10
|
+
if (nameIndex >= 0) return nameIndex;
|
|
11
|
+
|
|
12
|
+
const legacyIndex = Number(storedTab);
|
|
13
|
+
if (
|
|
14
|
+
Number.isInteger(legacyIndex) &&
|
|
15
|
+
legacyIndex >= 0 &&
|
|
16
|
+
legacyIndex < features.length
|
|
17
|
+
) {
|
|
18
|
+
return legacyIndex;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
package/src/ui/theme/colors.ts
CHANGED
|
@@ -14,6 +14,13 @@ export const Colors = {
|
|
|
14
14
|
|
|
15
15
|
purple: '#AF52DE',
|
|
16
16
|
|
|
17
|
+
// Panel-specific
|
|
18
|
+
railBackground: '#E8EEF6',
|
|
19
|
+
panelDivider: '#CED8E4',
|
|
20
|
+
signalRedBg: '#FFE9E7',
|
|
21
|
+
signalAmberBg: '#FFF1D6',
|
|
22
|
+
signalDefaultBg: '#E7EDF5',
|
|
23
|
+
|
|
17
24
|
get: '#007AFF',
|
|
18
25
|
post: '#34C759',
|
|
19
26
|
put: '#FF9500',
|