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

Add button for dev menu #42

Merged
merged 3 commits into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
8 changes: 8 additions & 0 deletions packages/vscode-extension/lib/wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ export function PreviewAppWrapper({ children, ...rest }) {
newRoute && push(newRoute);
});

agent._bridge.addListener("RNIDE_iosDevMenu", (_payload) => {
// this native module is present only on iOS and will crash if called
// on Android
const DevMenu = require("react-native/Libraries/NativeModules/specs/NativeDevMenu").default;

DevMenu.show();
});

LogBox.uninstall();
const LoadingView = require("react-native/Libraries/Utilities/LoadingView");
LoadingView.showMessage = (message) => {
Expand Down
1 change: 1 addition & 0 deletions packages/vscode-extension/src/common/Project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@

// important: order of values in this enum matters
export enum StartupMessage {
InitializingDevice = "Initializing device",

Check warning on line 26 in packages/vscode-extension/src/common/Project.ts

View workflow job for this annotation

GitHub Actions / check

Enum Member name `InitializingDevice` must match one of the following formats: camelCase
StartingPackager = "Starting packager",

Check warning on line 27 in packages/vscode-extension/src/common/Project.ts

View workflow job for this annotation

GitHub Actions / check

Enum Member name `StartingPackager` must match one of the following formats: camelCase
BootingDevice = "Booting device",
Building = "Building",
Installing = "Installing",
Expand Down Expand Up @@ -79,6 +79,7 @@
focusExtensionLogsOutput(): Promise<void>;
focusDebugConsole(): Promise<void>;
openNavigation(navigationItemID: string): Promise<void>;
openDevMenu(): Promise<void>;

dispatchTouch(xRatio: number, yRatio: number, type: "Up" | "Move" | "Down"): Promise<void>;
dispatchKeyPress(keyCode: number, direction: "Up" | "Down"): Promise<void>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ export class AndroidEmulatorDevice extends DeviceBase {
super();
}

public get platform(): Platform {
return Platform.Android;
}

public dispose(): void {
super.dispose();
this.emulatorProcess?.kill();
Expand Down Expand Up @@ -103,6 +107,10 @@ export class AndroidEmulatorDevice extends DeviceBase {
this.serial = await initPromise;
}

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

async configureMetroPort(packageName: string, metroPort: number) {
// read preferences
let prefs: any;
Expand Down
2 changes: 2 additions & 0 deletions packages/vscode-extension/src/devices/DeviceBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Disposable } from "vscode";
import { Preview } from "./preview";
import { BuildResult } from "../builders/BuildManager";
import { DeviceSettings } from "../common/Project";
import { Platform } from "../common/DeviceManager";

export abstract class DeviceBase implements Disposable {
private preview: Preview | undefined;
Expand All @@ -11,6 +12,7 @@ export abstract class DeviceBase implements Disposable {
abstract installApp(build: BuildResult, forceReinstall: boolean): Promise<void>;
abstract launchApp(build: BuildResult, metroPort: number, devtoolsPort: number): Promise<void>;
abstract makePreview(): Preview;
abstract get platform(): Platform;

dispose() {
this.preview?.dispose();
Expand Down
4 changes: 4 additions & 0 deletions packages/vscode-extension/src/devices/IosSimulatorDevice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export class IosSimulatorDevice extends DeviceBase {
super();
}

public get platform(): Platform {
return Platform.IOS;
}

public dispose() {
super.dispose();
return exec("xcrun", ["simctl", "--set", getOrCreateDeviceSet(), "shutdown", this.deviceUDID]);
Expand Down
16 changes: 16 additions & 0 deletions packages/vscode-extension/src/project/deviceSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { DeviceBase } from "../devices/DeviceBase";
import { Logger } from "../Logger";
import { BuildResult, DisposableBuild } from "../builders/BuildManager";
import { DeviceSettings, StartupMessage } from "../common/Project";
import { Platform } from "../common/DeviceManager";
import { AndroidEmulatorDevice } from "../devices/AndroidEmulatorDevice";

const WAIT_FOR_DEBUGGER_TIMEOUT = 15000; // 15 seconds

Expand Down Expand Up @@ -125,6 +127,20 @@ export class DeviceSession implements Disposable {
this.devtools.send("RNIDE_openNavigation", { id });
}

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 === Platform.IOS) {
this.devtools.send("RNIDE_iosDevMenu");
} else {
await (this.device as AndroidEmulatorDevice).openDevMenu();
}
}

public startPreview(previewId: string) {
this.devtools.send("RNIDE_openPreview", { previewId });
}
Expand Down
6 changes: 3 additions & 3 deletions packages/vscode-extension/src/project/devtools.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Disposable } from "vscode";
import http from "http";
import { WebSocketServer } from "ws";
import { WebSocketServer, WebSocket } from "ws";
import { Logger } from "../Logger";

export class Devtools implements Disposable {
private _port = 0;
private server: any;
private socket: any;
private socket?: WebSocket;
private listeners: Set<(event: string, payload: any) => void> = new Set();
private startPromise: Promise<void> | undefined;

Expand Down Expand Up @@ -37,7 +37,7 @@ export class Devtools implements Disposable {
this.server = http.createServer(() => {});
const wss = new WebSocketServer({ server: this.server });

wss.on("connection", (ws: any) => {
wss.on("connection", (ws) => {
if (this.socket !== undefined) {
Logger.error("Devtools client already connected");
this.socket.close();
Expand Down
3 changes: 1 addition & 2 deletions packages/vscode-extension/src/project/metro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { exec, ChildProcess, lineReader } from "../utilities/subprocess";
import { Logger } from "../Logger";
import { extensionContext, getAppRootFolder } from "../utilities/extensionContext";
import { Devtools } from "./devtools";
import { Project } from "./project";
import stripAnsi from "strip-ansi";

export interface MetroDelegate {
Expand Down Expand Up @@ -137,7 +136,7 @@ export class Metro implements Disposable {
RCT_DEVTOOLS_PORT: this.devtools.port.toString(),
REACT_NATIVE_IDE_LIB_PATH: libPath,
// we disable env plugins as they add additional lines at the top of the bundle that are not
// taken into acount by source maps. As a result, this messes up line numbers reported by hermes
// taken into account by source maps. As a result, this messes up line numbers reported by hermes
// and makes it hard to translate them back to original locations. Once this is fixed, we
// can restore this plugin.
EXPO_NO_CLIENT_ENV_VARS: "true",
Expand Down
4 changes: 4 additions & 0 deletions packages/vscode-extension/src/project/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,10 @@ export class Project implements Disposable, MetroDelegate, ProjectInterface {
this.deviceSession?.openNavigation(navigationItemID);
}

public async openDevMenu() {
await this.deviceSession?.openDevMenu();
}

public startPreview(appKey: string) {
this.deviceSession?.startPreview(appKey);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useEffect, useState } from "react";
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
import "./shared/Dropdown.css";
import { useModal } from "../providers/ModalProvider";
Expand All @@ -10,13 +10,15 @@ import { useWorkspaceConfig } from "../providers/WorkspaceConfigProvider";

interface SettingsDropdownProps {
children: React.ReactNode;
isDeviceRunning: boolean;
project: ProjectInterface;
disabled?: boolean;
}

function SettingsDropdown({ project, children, disabled }: SettingsDropdownProps) {
function SettingsDropdown({ project, isDeviceRunning, children, disabled }: SettingsDropdownProps) {
const { panelLocation, update } = useWorkspaceConfig();
const { openModal } = useModal();

return (
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild disabled={disabled}>
Expand All @@ -41,6 +43,16 @@ function SettingsDropdown({ project, children, disabled }: SettingsDropdownProps
<span className="codicon codicon-device-mobile" />
Manage devices...
</DropdownMenu.Item>
{isDeviceRunning && (
<DropdownMenu.Item
className="dropdown-menu-item"
onSelect={() => {
project.openDevMenu();
}}>
<span className="codicon codicon-code" />
Open dev menu
</DropdownMenu.Item>
)}

<DropdownMenu.Sub>
<DropdownMenu.SubTrigger className="dropdown-menu-item">
Expand Down
5 changes: 4 additions & 1 deletion packages/vscode-extension/src/webview/views/PreviewView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,10 @@ function PreviewView() {
<span slot="start" className="codicon codicon-debug-console" />
Logs
</Button>
<SettingsDropdown project={project} disabled={devicesNotFound}>
<SettingsDropdown
project={project}
isDeviceRunning={projectState.status === "running"}
disabled={devicesNotFound}>
<IconButton
onClick={() => {
vscode.postMessage({ command: "openSettings" });
Expand Down
Loading