Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use metro message endpoint to dispatch dev menu request #598

Merged
merged 2 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions packages/vscode-extension/lib/wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,6 @@ const RNInternals = {
} catch (e) {}
throw new Error("Couldn't locate LoadingView module");
},
get DevMenu() {
return require("react-native/Libraries/NativeModules/specs/NativeDevMenu").default;
},
};

function getCurrentScene() {
Expand Down Expand Up @@ -246,12 +243,6 @@ export function PreviewAppWrapper({ children, initialProps, ..._rest }) {
[mainContainerRef]
);

useAgentListener(devtoolsAgent, "RNIDE_iosDevMenu", (_payload) => {
// this native module is present only on iOS and will crash if called
// on Android
RNInternals.DevMenu.show();
});

useAgentListener(
devtoolsAgent,
"RNIDE_showStorybookStory",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,6 @@ export class AndroidEmulatorDevice extends DeviceBase {
await this.changeSettings(settings);
}

async openDevMenu() {
await exec(ADB_PATH, ["-s", this.serial!, "shell", "input", "keyevent", "82"]);
}

async configureExpoDevMenu(packageName: string) {
if (packageName === "host.exp.exponent") {
// For expo go we are unable to change this setting as the APK is not debuggable
Expand Down
12 changes: 1 addition & 11 deletions packages/vscode-extension/src/project/deviceSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,17 +269,7 @@ export class DeviceSession implements Disposable {
}

public async openDevMenu() {
// on iOS, we can load native module and dispatch dev menu show method. On
// Android, this native module isn't available and we need to fallback to
// adb to send "menu key" (code 82) to trigger code path showing the menu.
//
// We could probably unify it in the future by running metro in interactive
// mode and sending keys to stdin.
if (this.device.platform === DevicePlatform.IOS) {
this.devtools.send("RNIDE_iosDevMenu");
} else {
await (this.device as AndroidEmulatorDevice).openDevMenu();
}
this.metro.openDevMenu();
kmagiera marked this conversation as resolved.
Show resolved Hide resolved
}

public startPreview(previewId: string) {
Expand Down
17 changes: 17 additions & 0 deletions packages/vscode-extension/src/project/metro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import { shouldUseExpoCLI } from "../utilities/expoCli";
import { Devtools } from "./devtools";
import { getLaunchConfiguration } from "../utilities/launchConfiguration";
import WebSocket from "ws";

Check warning on line 11 in packages/vscode-extension/src/project/metro.ts

View workflow job for this annotation

GitHub Actions / check

`ws` import should occur before import of `../utilities/subprocess`

export interface MetroDelegate {
onBundleError(): void;
Expand Down Expand Up @@ -234,6 +235,22 @@
await appReady;
}

public async openDevMenu() {
// to send request to open dev menu, we route it through metro process
// that maintains a websocket connection with the device. Specifically,
// /message endpoint is used to send messages to the device, and metro proxies
// messages between different clients connected to that endpoint.
// Therefore, to send the message to the device we:
// 1. connect to the /message endpoint over websocket
// 2. send specifically formatted message to open dev menu
const ws = new WebSocket(`ws://localhost:${this._port}/message`);
await new Promise((resolve) => ws.addEventListener("open", resolve));
ws.send(
JSON.stringify({ version: 2 /* protocol version, needs to be set to 2 */, method: "devMenu" })
);
ws.close();
}

public async getDebuggerURL() {
const WAIT_FOR_DEBUGGER_TIMEOUT_MS = 15_000;

Expand Down
Loading