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.
Files changed (40) hide show
  1. package/AGENTS.md +341 -0
  2. package/app.js +22 -4448
  3. package/index.html +12 -0
  4. package/init.js +187 -0
  5. package/main.js +1 -0
  6. package/package.json +4 -2
  7. package/panels/console.js +788 -0
  8. package/panels/ga4.js +328 -0
  9. package/panels/native.js +256 -0
  10. package/panels/network.js +968 -0
  11. package/{src/renderer/panels → panels}/performance.js +51 -14
  12. package/panels/react.js +21 -0
  13. package/panels/redux.js +438 -0
  14. package/panels/settings.js +832 -0
  15. package/panels/sources.js +282 -0
  16. package/{src/renderer/panels → panels}/storage.js +77 -26
  17. package/styles.css +40 -7
  18. package/src/main/main.js +0 -396
  19. package/src/main/preload.js +0 -28
  20. package/src/renderer/app.js +0 -221
  21. package/src/renderer/components/object-tree.js +0 -245
  22. package/src/renderer/index.html +0 -111
  23. package/src/renderer/panels/console.js +0 -248
  24. package/src/renderer/panels/memory.js +0 -60
  25. package/src/renderer/panels/network.js +0 -559
  26. package/src/renderer/panels/react.js +0 -31
  27. package/src/renderer/panels/redux.js +0 -159
  28. package/src/renderer/panels/settings.js +0 -93
  29. package/src/renderer/panels/sources.js +0 -189
  30. package/src/renderer/state.js +0 -132
  31. package/src/renderer/styles/components.css +0 -145
  32. package/src/renderer/styles/console.css +0 -73
  33. package/src/renderer/styles/main.css +0 -229
  34. package/src/renderer/styles/network.css +0 -242
  35. package/src/renderer/styles/performance.css +0 -45
  36. package/src/renderer/styles/redux.css +0 -77
  37. package/src/renderer/styles/settings.css +0 -63
  38. package/src/renderer/styles/sources.css +0 -48
  39. package/src/renderer/styles/storage.css +0 -28
  40. 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.5",
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
- "src/"
45
+ "AGENTS.md"
44
46
  ],
45
47
  "scripts": {
46
48
  "start": "unset ELECTRON_RUN_AS_NODE && electron .",