Skip to content

Conversation

@ohah
Copy link
Owner

@ohah ohah commented Feb 11, 2026

feat/inspector-adb-reverse-and-tabs-fix

Purpose

Improve Inspector and Metro proxy behavior: FSD refactor for title bar and tabs visibility, and fix React Native Inspector reconnect and Redux/AsyncStorage after refresh.

Work content

  • Inspector FSD refactor

    • Added features/tabs-visibility: getTabsVisibility / useTabsVisibility and tab visibility toggle UI; used by the title bar and by the devtools page and routes.
    • Added widgets/title-bar: TitleBar component that uses tabs visibility; root layout now only handles server start, SSE, and settings modal and composes <TitleBar />.
    • Tests were added for the tabs-visibility feature (getTabsVisibility for unset/"true"/"false"/other, useTabsVisibility for initial state, toggle updating state and localStorage, and tabs-visibility-change dispatch).
  • Server Metro proxy

    • When an RN inspector is already connected and a new Metro proxy DevTools connection is established (e.g. after Inspector refresh), the server sends the reconnect inject again so __ChromeRemoteDevToolsReconnect() runs and the app reconnects.
    • When a new DevTools client connects and an RN inspector is already present, the server sends cached Redux stores to that client so the Redux/AsyncStorage panel works after refresh.
    • Added INJECT_RECONNECT_EXPRESSION and a unit test that checks the inject payload shape (Runtime.evaluate with expression containing __ChromeRemoteDevToolsReconnect).
  • React Native Inspector – MMKV DevTools

    • Fixed type error when passing v3 (legacy) MMKV to registerMMKVDevTools: getBuffer now typed as ArrayBufferLike so SharedArrayBuffer is accepted; exported MMKVStorageInput; example app uses it for the storages object.
    • Reduced intermittent empty MMKV tab in Tauri build: setMMKVConnectionReady() now calls sendAllSnapshots() so snapshots are sent when the WebSocket connects, even if the MMKV panel had opened earlier.
  • Inspector (Tauri) – adb reverse and Toast

    • Replaced custom adb result popup with Radix UI Toast (@radix-ui/react-toast); Provider and Viewport in app root, Toast in title bar for success/error.
    • adb reverse button now runs reverse for both Server URL port (8080) and Metro URL port (8081); added getMetroPort() in server-url and run both via Promise.all when ports differ. Single toast summarizes result.

How to test

  • Inspector: Run Inspector (web or Tauri), toggle tabs visibility from the title bar; confirm devtools page and routes respect the setting. Run bun test in the inspector package for tabs-visibility tests.
  • Metro proxy: Connect an RN app via Metro proxy, open Inspector, then refresh the Inspector tab; confirm the app reconnects and Redux/AsyncStorage panel shows data. Run cargo test -p chrome-remote-devtools-server for the inject payload test.
  • MMKV (Tauri): Run RN example with Tauri Inspector; open MMKV tab before/after connection; confirm all storages (user, cache, default, legacy) appear. No type error when building the example with v3 legacy storage.
  • adb reverse (Tauri): In Tauri Inspector, click the terminal icon in the title bar; confirm a toast (not alert) shows success or error; confirm both tcp:8080 and tcp:8081 are reversed when Server and Metro URLs use different ports.

Relates to #59

ohah added 2 commits February 11, 2026 19:36
- Add features/tabs-visibility (getTabsVisibility, useTabsVisibility, toggle UI)
- Add widgets/title-bar (TitleBar using tabs visibility)
- Simplify __root.tsx to layout, server start, SSE, settings modal only
- Import getTabsVisibility from feature in devtools page and routes
- Add use-tabs-visibility unit tests
…w DevTools

- When existing RN inspector: send reconnect inject again so refresh triggers
  __ChromeRemoteDevToolsReconnect()
- When new DevTools connects and RN already exists: send cached Redux stores
  so Redux/AsyncStorage panel works after Inspector refresh
- Add INJECT_RECONNECT_EXPRESSION constant and unit test for payload shape
@ohah ohah self-assigned this Feb 11, 2026
@ohah ohah added enhancement New feature or request refactor refactor labels Feb 11, 2026
@github-actions
Copy link

github-actions bot commented Feb 11, 2026

📊 Test Coverage Report - Inspector

Summary

Metric Coverage
Functions 60.98%
Lines 68.32%

File Coverage

Click to expand
File Functions Lines Uncovered Lines
happydom.ts 100.00% 100.00% N/A
packages/inspector/src/app/providers/index.tsx 100.00% 100.00% N/A
packages/inspector/src/app/router.ts 100.00% 100.00% N/A
packages/inspector/src/entities/client/api/client.queries.ts 75.00% 100.00% N/A
packages/inspector/src/entities/client/api/get-clients.ts 100.00% 100.00% N/A
packages/inspector/src/entities/client/index.ts 100.00% 100.00% N/A
packages/inspector/src/features/client-list/index.ts 100.00% 100.00% N/A
packages/inspector/src/features/client-list/lib/filter-clients.ts 100.00% 100.00% N/A
packages/inspector/src/features/replay/lib/constants.ts 100.00% 100.00% N/A
packages/inspector/src/features/replay/lib/message-sender.ts 100.00% 100.00% N/A
packages/inspector/src/features/replay/lib/response-body-store.ts 100.00% 100.00% N/A
packages/inspector/src/features/settings/index.ts 100.00% 100.00% N/A
packages/inspector/src/features/tabs-visibility/index.ts 100.00% 100.00% N/A
packages/inspector/src/features/tabs-visibility/model/use-tabs-visibility.ts 100.00% 100.00% N/A
packages/inspector/src/routeTree.gen.ts 100.00% 100.00% N/A
packages/inspector/src/routes/devtools/$clientId.tsx 100.00% 100.00% N/A
packages/inspector/src/shared/api/query-client.ts 100.00% 100.00% N/A
packages/inspector/src/shared/lib/constants.ts 100.00% 100.00% N/A
packages/inspector/src/shared/lib/file-to-cdp.ts 100.00% 100.00% N/A
packages/inspector/src/shared/lib/index.ts 100.00% 100.00% N/A
packages/inspector/src/shared/lib/url-validation.ts 100.00% 100.00% N/A
packages/inspector/src/shared/ui/index.ts 100.00% 100.00% N/A
packages/inspector/src/widgets/title-bar/index.ts 100.00% 100.00% N/A
packages/inspector/src/components/ui/button.tsx 0.00% 91.67% 40-42
packages/inspector/src/features/replay/lib/message-handlers.ts 92.86% 87.18% 44,209-227
packages/inspector/src/features/replay/lib/cdp-message-utils.ts 77.78% 85.45% 23,33-36,55,90
packages/inspector/src/features/replay/lib/message-sender-extended.ts 94.12% 85.21% 132-134,136-140,161-162,171-174,202,240,245-249
packages/inspector/src/entities/client/api/get-metro-targets.ts 100.00% 84.62% 39-45
packages/inspector/src/features/replay/lib/extractors.ts 91.67% 83.54% 70,87-91,101,127-128,131-133,181,184-189,191-196
packages/inspector/src/shared/lib/server-url.ts 76.92% 81.08% 40-44,51,95,105-111
packages/inspector/src/routes/__root.tsx 66.67% 79.41% 21-26
packages/inspector/src/shared/lib/settings-modal-store.ts 20.00% 77.78% 20
packages/inspector/src/shared/lib/devtools-url.ts 87.50% 67.90% 27,82,86,137-159
packages/inspector/src/lib/utils.ts 0.00% 66.67% N/A
packages/inspector/src/entities/client/api/use-clients-list-sse.ts 33.33% 65.38% 25-29,43-46
packages/inspector/src/components/ui/tooltip.tsx 0.00% 47.62% 15-25
packages/inspector/src/entities/client/api/metro.queries.ts 0.00% 43.75% 15-23
packages/inspector/src/features/tabs-visibility/ui/tab-visibility-toggle.tsx 0.00% 16.67% 9-28
packages/inspector/src/features/settings/ui/settings-modal.tsx 33.33% 8.70% 14,16-19,22-28,30-32,35-36,38-42,44-49,51-59,62-66
packages/inspector/src/routes/mode/$mode.tsx 0.00% 7.73% 15-21,27-186
packages/inspector/src/shared/ui/empty-states.tsx 0.00% 6.90% 7-12,29-49
packages/inspector/src/routes/index.tsx 0.00% 6.14% 18-231
packages/inspector/src/routes/replay.tsx 0.00% 5.60% 22-240
packages/inspector/src/widgets/title-bar/ui/TitleBar.tsx 0.00% 3.85% 18-242
packages/inspector/src/features/client-list/ui/client-filter.tsx 0.00% 3.45% 13-40
packages/inspector/src/pages/devtools/index.tsx 0.00% 3.07% 20-23,30-436
packages/inspector/src/components/tabs.tsx 0.00% 2.94% 20-85
packages/inspector/src/features/client-list/ui/client-table.tsx 0.00% 1.90% 11-113
packages/inspector/src/features/settings/ui/server-settings.tsx 0.00% 1.56% 15-140
packages/inspector/src/features/client-list/ui/client-select.tsx 0.00% 0.00% 10-27

Generated by test coverage script

@github-actions
Copy link

github-actions bot commented Feb 11, 2026

📊 Test Coverage Report - Server

Summary

Metric Coverage
Lines 23.12%
Functions 100.00%
Branches 0.00%

File Coverage

Click to expand
File Lines Functions Branches Uncovered Lines
crates/server/src/socket_server/metro_proxy_handler/url_rewriting.rs 96.24% 100.00% 0.00% 14, 46, 61, 89, 103-105
crates/server/src/config.rs 96.12% 100.00% 0.00% 147, 152, 157, 162
crates/server/src/react_native/inspector_connection.rs 68.56% 100.00% 0.00% 169-180, 182-183, 201, 213-228, 231-246, 249-265, 268-272, 274, 276, 279-290
crates/server/src/socket_server/message_processor.rs 65.75% 100.00% 0.00% 15, 17-21, 23-31, 33, 35, 39-44, 48-49
crates/server/src/socket_server/mod.rs 35.93% 100.00% 0.00% 90-92, 95-97, 100-109, 111-122, 124-131, 133, 135-141, 145-147, 150, 152-154, 157, 161-170, 173-1...
crates/server/src/logging.rs 31.54% 100.00% 0.00% 19-24, 26, 46-50, 54-56, 67-69, 75, 77-82, 84, 97-104, 114-121, 141, 149-156, 158-161, 163-166, 1...
crates/server/src/socket_server/metro_proxy_handler/handler.rs 3.08% 100.00% 0.00% 34-40, 42-43, 45-51, 55-56, 58-64, 69-70, 72-78, 82-91, 94-103, 107-113, 116-117, 123-127, 130-14...
crates/server/src/http_routes.rs 0.00% 100.00% 0.00% 21-35, 40-47, 49, 53, 55-56, 59-65, 68-74, 78-82, 84, 86-88, 92-94, 96-98, 101-104, 106-110, 112,...
crates/server/src/lib.rs 0.00% 100.00% 0.00% 61-67, 71-84, 86-88, 90, 94-95, 98, 101-103, 106-107, 110, 113-125, 127-128, 131-135, 137, 141-14...
crates/server/src/server.rs 0.00% 100.00% 0.00% 16-20, 23-25, 30-34, 36, 39-43, 46-61, 64, 66-77, 80-87, 92-93, 95-97, 99-101, 106-110, 112-113, ...
crates/server/src/socket_server/client_handler.rs 0.00% 100.00% 0.00% 20, 22-25, 28-30, 32-33, 37-47, 49-50, 52-60, 63-77, 81-82, 89-101, 103, 106-116, 119-120, 123-12...
crates/server/src/socket_server/devtools_handler.rs 0.00% 100.00% 0.00% 14-27, 29-32, 34-35, 38-39, 41-45, 48-49, 52-71, 74, 76-77, 79, 81, 83-90, 92-109, 111-112, 115-1...
crates/server/src/socket_server/metro_proxy_handler/mod.rs 0.00% 100.00% 0.00% 12-18
crates/server/src/socket_server/react_native_handler.rs 0.00% 100.00% 0.00% 16-26, 28-29, 32-38, 41-43, 46-48, 55-59, 61-80, 84-97, 100-112, 115-117, 119-133, 136-146, 150-1...

Generated by Rust test coverage script (cargo-llvm-cov)

@github-actions
Copy link

github-actions bot commented Feb 11, 2026

Integration Tests

1 tests   1 ✅  13s ⏱️
1 suites  0 💤
1 files    0 ❌

Results for commit 3dcf43c.

♻️ This comment has been updated with latest results.

@github-actions
Copy link

github-actions bot commented Feb 11, 2026

📊 Test Results

✅ Test Status: PASSED

📸 Screenshots

Screenshots are available as artifacts. Download them here.

Artifact name: playwright-screenshots

Screenshot files
  1. test-client-rn-2.png (test-client-rn-2)
  2. test-client-web-1.png (test-client-web-1)
  3. test-client-web-2.png (test-client-web-2)
  4. test-client-rn-1.png (test-client-rn-1)

Copy link
Owner Author

@ohah ohah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review

Purpose and description

The PR description matches the changes: FSD refactor for title bar and tabs visibility, and Metro proxy fixes for reconnect on refresh and cached Redux for new DevTools. Root is simplified; server sends a second inject when RN is already connected and pushes cached Redux stores to newly connected DevTools.

What's done well

  • Clear separation: features/tabs-visibility and widgets/title-bar follow FSD; root only handles layout, server start, SSE, and settings.
  • Reconnect behavior: re-sending the inject when rn_connection_id.is_some() correctly covers the Inspector-refresh case (new DevTools iframe = new Metro proxy connection).
  • Cached Redux: sending INIT_INSTANCE + INIT for each cached store to the new DevTools restores the Redux/AsyncStorage panel after refresh.
  • INJECT_RECONNECT_EXPRESSION is extracted and tested; the unit test locks the payload shape.
  • Tabs visibility is covered by tests (getTabsVisibility, useTabsVisibility, toggle and event).
  • Root no longer starts the server on every load when it is already running (is_server_running check), avoiding Metro proxy WS drops on refresh.

Improvement suggestions

  • Magic number: The 200 ms delay before sending cached Redux could be a named constant (e.g. REDUX_CACHE_SEND_DELAY_MS) so the intent and tuning point are clear (see inline).
  • Edge case: If the RN app disconnects between spawning the Redux-send task and the 200 ms sleep, the task will still run and send to the DevTools; that is acceptable (no stale association). If desired, a short comment could note that the delay allows the new DevTools to be ready.
  • Tests: Current tests are good; no further changes required for this PR.

Testing

  • Run Inspector (web/Tauri), toggle tabs visibility, confirm devtools page and routes respect it; run bun test in inspector for tabs-visibility.
  • Connect RN via Metro proxy, open Inspector, refresh the Inspector tab: app should reconnect and Redux/AsyncStorage panel should show data; run cargo test -p chrome-remote-devtools-server for the inject test.

let rn_manager_redux = rn_manager.clone();
let logger_redux = logger.clone();
let metro_id_redux = metro_devtools_id.clone();
let inspector_id_for_redux = conn_id.clone();
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding a module-level constant (e.g. REDUX_CACHE_SEND_DELAY_MS: u64 = 200) and using it here so the intent and tuning point are clear.

@ohah
Copy link
Owner Author

ohah commented Feb 11, 2026

Maintainability perspective

  • Complexity and readability: Root and handler are in good shape. The 200 ms delay in the Redux cache send is a magic number; a named constant would improve clarity and make future tuning easier.
  • Duplication and consistency: FSD layout is consistent (features vs widgets). Tabs visibility is used in one place (TitleBar) and read in devtools/routes via the shared getter; no duplication.
  • Dependencies and coupling: TitleBar and tabs-visibility stay within inspector; the server only adds logic in the existing metro proxy handler. No new external deps; no circular imports.
  • Documentation and types: JSDoc and doc comments (including bilingual) are present on new modules and the inject constant. Types are clear (no unnecessary any).
  • Tests: Tabs-visibility has unit tests; the handler has a focused test for the inject payload shape. Both are maintainable and tied to behavior, not implementation details.

@ohah
Copy link
Owner Author

ohah commented Feb 11, 2026

Unnecessary fallback / scripts perspective

  • Fallback paths: The “second inject when RN already connected” and “send cached Redux to new DevTools” paths are justified: they address real scenarios (Inspector refresh and new DevTools iframe). No unnecessary alternate paths.
  • Scripts: No new scripts; no overlap with existing tooling.
  • Defensive code: The is_server_running check before start_server in root is appropriate (avoids restart on refresh). The if let Some(ref conn_id) before spawning the Redux cache task is correct (only run when we have an RN connection). No redundant null checks or double-init.
  • Alternate implementations: Single implementation for inject and Redux cache; no polyfills or “if A fails use B” added.

Nothing in this PR looks like unnecessary fallback or script bloat.

…y tab

- Use ArrayBufferLike for MMKV getBuffer so v3 (SharedArrayBuffer) is accepted
- Export MMKVStorageInput; example app uses it for registerMMKVDevTools
- Call sendAllSnapshots() in setMMKVConnectionReady() so snapshots are sent
  when WebSocket connects, avoiding empty MMKV tab when panel opened early
@github-actions
Copy link

github-actions bot commented Feb 11, 2026

📊 Test Coverage Report - React Native Inspector

Summary

Metric Coverage
Functions 80.27%
Lines 73.38%

File Coverage

Click to expand
File Functions Lines Uncovered Lines
happydom.ts 100.00% 100.00% N/A
packages/react-native-inspector/src/cdp/common/object-store.ts 100.00% 100.00% N/A
packages/react-native-inspector/src/cdp/domain/protocol.ts 100.00% 100.00% N/A
packages/react-native-inspector/src/device-id.ts 100.00% 100.00% N/A
packages/react-native-inspector/src/cdp/domain/runtime.ts 100.00% 96.27% 147,149-152
packages/react-native-inspector/src/metro-config.cjs 100.00% 94.12% 33,35-36
packages/react-native-inspector/src/server-info.ts 100.00% 92.31% N/A
packages/react-native-inspector/src/cdp/common/get-object-properties.ts 100.00% 91.43% 31,39
packages/react-native-inspector/src/utils.ts 100.00% 90.91% 14-15
packages/react-native-inspector/src/cdp/common/value-to-remote-object.ts 100.00% 90.23% 53,56,66,69,73,76,81-82,84-85,102,196-197
packages/react-native-inspector/src/redux-devtools-extension.ts 84.85% 88.12% 106,113,115,117,127,136-143,146-157,167,169,174-178,463-466,519,523,525-527
packages/react-native-inspector/src/websocket-client.ts 80.00% 82.86% 80-85,90-95,117-121
packages/react-native-inspector/src/cdp/domain/base.ts 100.00% 80.43% 45,58-62,69-71
packages/react-native-inspector/src/cdp/domain/network.ts 76.92% 68.50% 21-22,37,67,100-114,125,236-239,254-258,261-264,267-292,296-305,308-317,326-327,331-333,336-337,360,370-373,388,390-391,420-421,423-429,435,470,475-485,513-519,523-529,536,554,581-591
packages/react-native-inspector/src/cdp/domain/runtime-evaluate.ts 100.00% 62.50% 20,23,26,33-44,61-71,85-88,101,105-106,121,125-126
packages/react-native-inspector/src/cdp-message-handler.ts 68.75% 59.92% 23-29,54-90,103-113,115,117-118,141-146,151-157,168,171-175,178,181-182,245-249,251-253,255-256,258-260,262-263
packages/react-native-inspector/src/cdp-message.ts 100.00% 56.25% 28-33
packages/react-native-inspector/src/mmkv/mmkv-adapter.ts 36.36% 52.78% 47-62
packages/react-native-inspector/src/mmkv/utils.ts 50.00% 44.12% 23,40,42,44-46,48,53,55,57-60,63-65,67-69
packages/react-native-inspector/src/mmkv/index.ts 31.58% 35.12% 21-37,44-46,54-55,63-71,79-89,98-112,120-129,136-139,173-185,191,201,205-249,312-322,326-339
packages/react-native-inspector/src/mmkv/mmkv-view.ts 37.50% 21.35% 27-30,44-97,101-112
packages/react-native-inspector/src/mmkv/is-garbled.ts 0.00% 7.14% 6-18

Generated by test coverage script

@github-actions
Copy link

github-actions bot commented Feb 11, 2026

📱 Maestro Android Test Results

PASSED

Maestro Android tests have completed. Check the workflow run for details.

@github-actions
Copy link

github-actions bot commented Feb 11, 2026

📱 Maestro iOS Test Results

PASSED

Maestro iOS tests have completed. Check the workflow run for details.

…d 8081

- Replace custom toast with @radix-ui/react-toast; add Provider and Viewport in app
- Run adb reverse for both Server URL port (8080) and Metro URL port (8081)
- Add getMetroPort() in server-url; tooltip shows both ports
@ohah ohah merged commit d5e443d into main Feb 11, 2026
20 checks passed
@ohah ohah deleted the feat/inspector-adb-reverse-and-tabs-fix branch February 11, 2026 17:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request refactor refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant