reactoradar 1.6.5 → 1.6.7
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/AGENTS.md +341 -0
- package/app.js +22 -4448
- package/index.html +12 -0
- package/init.js +187 -0
- package/main.js +1 -0
- package/package.json +4 -2
- package/panels/console.js +788 -0
- package/panels/ga4.js +328 -0
- package/panels/native.js +256 -0
- package/panels/network.js +968 -0
- package/{src/renderer/panels → panels}/performance.js +51 -14
- package/panels/react.js +21 -0
- package/panels/redux.js +438 -0
- package/panels/settings.js +832 -0
- package/panels/sources.js +282 -0
- package/{src/renderer/panels → panels}/storage.js +77 -26
- package/styles.css +40 -7
- package/src/main/main.js +0 -396
- package/src/main/preload.js +0 -28
- package/src/renderer/app.js +0 -221
- package/src/renderer/components/object-tree.js +0 -245
- package/src/renderer/index.html +0 -111
- package/src/renderer/panels/console.js +0 -248
- package/src/renderer/panels/memory.js +0 -60
- package/src/renderer/panels/network.js +0 -559
- package/src/renderer/panels/react.js +0 -31
- package/src/renderer/panels/redux.js +0 -159
- package/src/renderer/panels/settings.js +0 -93
- package/src/renderer/panels/sources.js +0 -189
- package/src/renderer/state.js +0 -132
- package/src/renderer/styles/components.css +0 -145
- package/src/renderer/styles/console.css +0 -73
- package/src/renderer/styles/main.css +0 -229
- package/src/renderer/styles/network.css +0 -242
- package/src/renderer/styles/performance.css +0 -45
- package/src/renderer/styles/redux.css +0 -77
- package/src/renderer/styles/settings.css +0 -63
- package/src/renderer/styles/sources.css +0 -48
- package/src/renderer/styles/storage.css +0 -28
- package/src/renderer/styles/theme-light.css +0 -57
package/index.html
CHANGED
|
@@ -90,6 +90,18 @@
|
|
|
90
90
|
|
|
91
91
|
</div>
|
|
92
92
|
|
|
93
|
+
<!-- Load order: app.js (state/helpers) → panels → init.js (IPC/boot) -->
|
|
93
94
|
<script src="app.js"></script>
|
|
95
|
+
<script src="panels/settings.js"></script>
|
|
96
|
+
<script src="panels/console.js"></script>
|
|
97
|
+
<script src="panels/network.js"></script>
|
|
98
|
+
<script src="panels/ga4.js"></script>
|
|
99
|
+
<script src="panels/redux.js"></script>
|
|
100
|
+
<script src="panels/storage.js"></script>
|
|
101
|
+
<script src="panels/performance.js"></script>
|
|
102
|
+
<script src="panels/native.js"></script>
|
|
103
|
+
<script src="panels/react.js"></script>
|
|
104
|
+
<script src="panels/sources.js"></script>
|
|
105
|
+
<script src="init.js"></script>
|
|
94
106
|
</body>
|
|
95
107
|
</html>
|
package/init.js
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// init.js — IPC wiring, button handlers, memory monitor, and panel initialization
|
|
3
|
+
// This file loads LAST — after app.js (state/helpers) and all panel scripts.
|
|
4
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
5
|
+
|
|
6
|
+
// ─── CDP Button ───────────────────────────────────────────────────────────────
|
|
7
|
+
$('btnCDP')?.addEventListener('click', () => {
|
|
8
|
+
window.electronAPI?.openCDPTarget(null);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
// ─── Screenshot Button ────────────────────────────────────────────────────────
|
|
12
|
+
$('btnScreenshot')?.addEventListener('click', takeScreenshot);
|
|
13
|
+
|
|
14
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
15
|
+
// IPC from Main
|
|
16
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
17
|
+
if (window.electronAPI) {
|
|
18
|
+
window.electronAPI.on('ports', ports => { state.ports = ports; });
|
|
19
|
+
|
|
20
|
+
window.electronAPI.on('cdp-targets', targets => {
|
|
21
|
+
state.cdpTargets = targets;
|
|
22
|
+
const btn = $('btnCDP');
|
|
23
|
+
if (btn) {
|
|
24
|
+
const hasCDP = targets?.length > 0;
|
|
25
|
+
const port = state.ports?.METRO || getStoredMetroPort();
|
|
26
|
+
btn.textContent = hasCDP
|
|
27
|
+
? `JS Debugger (:${port}) [${targets.length}] ↗`
|
|
28
|
+
: `JS Debugger (:${port}) ↗`;
|
|
29
|
+
btn.style.opacity = hasCDP ? '1' : '0.5';
|
|
30
|
+
if (hasCDP) {
|
|
31
|
+
btn.onclick = () => window.electronAPI.openCDPTarget(targets[0].webSocketDebuggerUrl);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
window.electronAPI.on('redux-event', handleReduxEvent);
|
|
37
|
+
window.electronAPI.on('network-event', handleNetworkEvent);
|
|
38
|
+
window.electronAPI.on('storage-event', handleStorageEvent);
|
|
39
|
+
|
|
40
|
+
window.electronAPI.on('console-event', addConsoleLog);
|
|
41
|
+
window.electronAPI.on('ga4-event', handleGA4Event);
|
|
42
|
+
|
|
43
|
+
window.electronAPI.on('perf-event', event => {
|
|
44
|
+
handlePerfEvent(event);
|
|
45
|
+
handleMemoryEvent(event);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
window.electronAPI.on('clear-all-ui', clearAll);
|
|
49
|
+
|
|
50
|
+
// When all device bridges disconnect, release heavy memory but keep logs visible.
|
|
51
|
+
// Debounced to avoid data loss during hot reloads or flaky connections.
|
|
52
|
+
let _disconnectTimer = null;
|
|
53
|
+
window.electronAPI.on('device-all-disconnected', () => {
|
|
54
|
+
clearTimeout(_disconnectTimer);
|
|
55
|
+
_disconnectTimer = setTimeout(() => {
|
|
56
|
+
console.log('[App] All devices disconnected — freeing memory');
|
|
57
|
+
freeMemory();
|
|
58
|
+
}, 3000);
|
|
59
|
+
});
|
|
60
|
+
// Cancel pending free if a device reconnects
|
|
61
|
+
const _cancelDisconnectTimer = () => { clearTimeout(_disconnectTimer); _disconnectTimer = null; };
|
|
62
|
+
window.electronAPI.on('redux-connected', on => { if (on) _cancelDisconnectTimer(); updateDeviceBanner('redux', on); });
|
|
63
|
+
window.electronAPI.on('network-connected', on => { if (on) _cancelDisconnectTimer(); updateDeviceBanner('network', on); });
|
|
64
|
+
window.electronAPI.on('storage-connected', on => { if (on) _cancelDisconnectTimer(); updateDeviceBanner('storage', on); });
|
|
65
|
+
window.electronAPI.on('react-dt-status', on => { updateDeviceBanner('reactDT', on); });
|
|
66
|
+
|
|
67
|
+
// Cmd+F — focus the search input for the active panel
|
|
68
|
+
function _handleFind() {
|
|
69
|
+
if (state.activePanel === 'network' && state.network.selectedId) {
|
|
70
|
+
const wrap = $('detailSearchWrap');
|
|
71
|
+
const input = $('detailSearchInput');
|
|
72
|
+
if (wrap && input) {
|
|
73
|
+
wrap.style.display = 'flex';
|
|
74
|
+
input.focus();
|
|
75
|
+
input.select();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const searchMap = {
|
|
80
|
+
console: 'consoleSearch',
|
|
81
|
+
network: 'netSearchInput',
|
|
82
|
+
ga4: 'ga4Search',
|
|
83
|
+
redux: 'reduxSearch',
|
|
84
|
+
storage: 'storageSearch',
|
|
85
|
+
};
|
|
86
|
+
const inputId = searchMap[state.activePanel];
|
|
87
|
+
if (inputId) {
|
|
88
|
+
const el = $(inputId);
|
|
89
|
+
if (el) { el.focus(); el.select(); }
|
|
90
|
+
}
|
|
91
|
+
if (state.activePanel === 'console') {
|
|
92
|
+
const bar = $('consoleFindBar');
|
|
93
|
+
if (bar) { bar.style.display = 'flex'; $('consoleFindInput')?.focus(); }
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
window.electronAPI.on('focus-search', _handleFind);
|
|
97
|
+
document.addEventListener('keydown', (e) => {
|
|
98
|
+
if ((e.metaKey || e.ctrlKey) && e.key === 'f') {
|
|
99
|
+
e.preventDefault();
|
|
100
|
+
_handleFind();
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
window.electronAPI.on('app-version', (version, isPackaged) => {
|
|
105
|
+
state._appVersion = version;
|
|
106
|
+
state._isPackaged = !!isPackaged;
|
|
107
|
+
document.querySelectorAll('#aboutVersion').forEach(el => el.textContent = 'v' + version);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
window.electronAPI.on('update-available', ({ current, latest, autoUpdate }) => {
|
|
111
|
+
state._updateAvailable = { current, latest, autoUpdate };
|
|
112
|
+
_applyUpdateBanner();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
window.electronAPI.on('update-downloaded', ({ version }) => {
|
|
116
|
+
state._updateDownloaded = version;
|
|
117
|
+
_applyUpdateBanner();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
window.electronAPI.on('trigger-open-cdp', () => {
|
|
121
|
+
window.electronAPI?.openCDPTarget(null);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
window.electronAPI.on('theme-changed', theme => {
|
|
125
|
+
document.documentElement.setAttribute('data-theme', theme);
|
|
126
|
+
setStoredTheme(theme);
|
|
127
|
+
document.querySelectorAll('#themeSwitcher .theme-card')
|
|
128
|
+
.forEach(b => b.classList.toggle('active', b.dataset.theme === theme));
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ─── Memory Monitor ──────────────────────────────────────────────────────────
|
|
133
|
+
let _memoryWarningShown = false;
|
|
134
|
+
setInterval(() => {
|
|
135
|
+
if (!window.performance || !performance.memory) return;
|
|
136
|
+
const used = performance.memory.usedJSHeapSize;
|
|
137
|
+
const limit = performance.memory.jsHeapSizeLimit;
|
|
138
|
+
const pct = used / limit;
|
|
139
|
+
if (pct > 0.7 && !_memoryWarningShown) {
|
|
140
|
+
_memoryWarningShown = true;
|
|
141
|
+
const banner = document.createElement('div');
|
|
142
|
+
banner.id = 'memoryWarning';
|
|
143
|
+
banner.className = 'memory-warning';
|
|
144
|
+
const usedMB = Math.round(used / 1024 / 1024);
|
|
145
|
+
banner.innerHTML = `<span>High memory usage (${usedMB}MB) — ReactoRadar may become unresponsive.</span>`
|
|
146
|
+
+ `<button class="memory-warn-btn" id="memWarnClear">Clear All Data</button>`
|
|
147
|
+
+ `<button class="memory-warn-btn" id="memWarnDismiss">Dismiss</button>`;
|
|
148
|
+
document.body.prepend(banner);
|
|
149
|
+
$('memWarnClear')?.addEventListener('click', () => {
|
|
150
|
+
state.console.logs = []; _consolePending = [];
|
|
151
|
+
_lastLogMsg = ''; _lastLogRow = null; _lastLogCount = 1;
|
|
152
|
+
$('cBadge').textContent = '0'; renderConsole();
|
|
153
|
+
state.network.requests = {}; state.network.order = []; state.network.selectedId = null;
|
|
154
|
+
$('nBadge').textContent = '0'; renderNetwork();
|
|
155
|
+
state.redux.actions = []; state.redux.states = []; state.redux.selected = -1;
|
|
156
|
+
$('rBadge').textContent = '0'; renderRedux();
|
|
157
|
+
banner.remove(); _memoryWarningShown = false;
|
|
158
|
+
});
|
|
159
|
+
$('memWarnDismiss')?.addEventListener('click', () => { banner.remove(); });
|
|
160
|
+
}
|
|
161
|
+
if (pct < 0.5) _memoryWarningShown = false;
|
|
162
|
+
}, 30000);
|
|
163
|
+
|
|
164
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
165
|
+
// Apply saved settings on load
|
|
166
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
167
|
+
applyTheme(getStoredTheme());
|
|
168
|
+
applyFontSize(getStoredFontSize());
|
|
169
|
+
applyFontFamily(getStoredFontFamily());
|
|
170
|
+
applyAppName(getStoredAppName());
|
|
171
|
+
applyTabVisibility();
|
|
172
|
+
window.electronAPI?.setMetroPort(getStoredMetroPort());
|
|
173
|
+
|
|
174
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
175
|
+
// INIT — Panel initialization (all panel scripts must be loaded before this)
|
|
176
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
177
|
+
initConsolePanel();
|
|
178
|
+
initNetworkPanel();
|
|
179
|
+
initGA4Panel();
|
|
180
|
+
initPerformancePanel();
|
|
181
|
+
initMemoryPanel();
|
|
182
|
+
initReduxPanel();
|
|
183
|
+
initStoragePanel();
|
|
184
|
+
initReactPanel();
|
|
185
|
+
initSourcesPanel();
|
|
186
|
+
initNativeLogsPanel();
|
|
187
|
+
initSettingsPanel();
|
package/main.js
CHANGED
|
@@ -375,6 +375,7 @@ function startReactDevToolsServer() {
|
|
|
375
375
|
function startBridgeServers() {
|
|
376
376
|
// Redux Bridge
|
|
377
377
|
startBridge(PORTS.REDUX_BRIDGE, 'redux', reduxClients, (event) => {
|
|
378
|
+
// console.log('[REDUX-DEBUG] Event from SDK:', event?.type, event?.action?.type);
|
|
378
379
|
_send('redux-event', event);
|
|
379
380
|
});
|
|
380
381
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reactoradar",
|
|
3
3
|
"productName": "ReactoRadar",
|
|
4
|
-
"version": "1.6.
|
|
4
|
+
"version": "1.6.7",
|
|
5
5
|
"description": "macOS debugger for React Native — Console, Sources, Network, Performance, Memory, Redux, AsyncStorage, React tree. Supports RN 0.74+ with Hermes and New Architecture.",
|
|
6
6
|
"main": "main.js",
|
|
7
7
|
"bin": {
|
|
@@ -36,11 +36,13 @@
|
|
|
36
36
|
"preload.js",
|
|
37
37
|
"index.html",
|
|
38
38
|
"app.js",
|
|
39
|
+
"init.js",
|
|
40
|
+
"panels/",
|
|
39
41
|
"styles.css",
|
|
40
42
|
"sdk/",
|
|
41
43
|
"bin/",
|
|
42
44
|
"assets/",
|
|
43
|
-
"
|
|
45
|
+
"AGENTS.md"
|
|
44
46
|
],
|
|
45
47
|
"scripts": {
|
|
46
48
|
"start": "unset ELECTRON_RUN_AS_NODE && electron .",
|