microsoft/vscode-react-native

Public

mirrored from https://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
267aac11f942068130da1a6e532653fb460bc8b8

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/extension/commandPaletteHandler.ts

131lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
4import * as vscode from "vscode";
5import * as Q from "q";
6import {CommandExecutor} from "../common/commandExecutor";
7import {SettingsHelper} from "./settingsHelper";
8import {Log} from "../common/log/log";
9import {Packager} from "../common/packager";
10import {AndroidPlatform} from "../common/android/androidPlatform";
11import {PackagerStatus, PackagerStatusIndicator} from "./packagerStatusIndicator";
12import {ReactNativeProjectHelper} from "../common/reactNativeProjectHelper";
13import {TargetPlatformHelper} from "../common/targetPlatformHelper";
14import {TelemetryHelper} from "../common/telemetryHelper";
15import {IOSDebugModeManager} from "../common/ios/iOSDebugModeManager";
16
17export class CommandPaletteHandler {
18 private reactNativePackager: Packager;
19 private reactNativePackageStatusIndicator: PackagerStatusIndicator;
20 private workspaceRoot: string;
21
22 constructor(workspaceRoot: string, reactNativePackager: Packager, packagerStatusIndicator: PackagerStatusIndicator) {
23 this.workspaceRoot = workspaceRoot;
24 this.reactNativePackager = reactNativePackager;
25 this.reactNativePackageStatusIndicator = packagerStatusIndicator;
26 }
27
28 /**
29 * Starts the React Native packager
30 */
31 public startPackager(): Q.Promise<void> {
32 return this.executeCommandInContext("startPackager", () =>
33 this.runStartPackagerCommandAndUpdateStatus());
34 }
35
36 /**
37 * Kills the React Native packager invoked by the extension's packager
38 */
39 public stopPackager(): Q.Promise<void> {
40 return this.executeCommandInContext("stopPackager", () => this.reactNativePackager.stop())
41 .then(() => this.reactNativePackageStatusIndicator.updatePackagerStatus(PackagerStatus.PACKAGER_STOPPED));
42 }
43
44 /**
45 * Restarts the React Native packager
46 */
47 public restartPackager(): Q.Promise<void> {
48 return this.executeCommandInContext("restartPackager", () =>
49 this.runRestartPackagerCommandAndUpdateStatus());
50 }
51
52 /**
53 * Executes the 'react-native run-android' command
54 */
55 public runAndroid(): Q.Promise<void> {
56 TargetPlatformHelper.checkTargetPlatformSupport("android");
57 return this.executeCommandInContext("runAndroid", () => this.executeWithPackagerRunning(() => {
58 const packagerPort = SettingsHelper.getPackagerPort();
59 return new AndroidPlatform({ projectRoot: this.workspaceRoot, packagerPort: packagerPort }).runApp(/*shouldLaunchInAllDevices*/true);
60 }));
61 }
62
63
64 /**
65 * Executes the 'react-native run-ios' command
66 */
67 public runIos(): Q.Promise<void> {
68 TargetPlatformHelper.checkTargetPlatformSupport("ios");
69 return this.executeCommandInContext("runIos", () => {
70 // Set the Debugging setting to disabled, because in iOS it's persisted across runs of the app
71 return new IOSDebugModeManager(this.workspaceRoot).setSimulatorJSDebuggingModeSetting(/*enable=*/ false)
72 .catch(() => { }) // If setting the debugging mode fails, we ignore the error and we run the run ios command anyways
73 .then(() => this.executeReactNativeRunCommand("run-ios"));
74 });
75 }
76
77 private runStartPackagerCommandAndUpdateStatus(): Q.Promise<void> {
78 return this.reactNativePackager.start(SettingsHelper.getPackagerPort(), false)
79 .then(() => this.reactNativePackageStatusIndicator.updatePackagerStatus(PackagerStatus.PACKAGER_STARTED));
80 }
81
82 private runRestartPackagerCommandAndUpdateStatus(): Q.Promise<void> {
83 return this.reactNativePackager.restart(SettingsHelper.getPackagerPort())
84 .then(() => this.reactNativePackageStatusIndicator.updatePackagerStatus(PackagerStatus.PACKAGER_STARTED));
85 }
86
87 /**
88 * Executes a react-native command passed after starting the packager
89 * {command} The command to be executed
90 * {args} The arguments to be passed to the command
91 */
92 private executeReactNativeRunCommand(command: string, args?: string[]): Q.Promise<void> {
93 return this.executeWithPackagerRunning(() => {
94 return new CommandExecutor(this.workspaceRoot).spawnReactCommand(command, args).outcome;
95 });
96 }
97
98 /**
99 * Executes a lambda function after starting the packager
100 * {lambda} The lambda function to be executed
101 */
102 private executeWithPackagerRunning(lambda: () => Q.Promise<void>): Q.Promise<void> {
103 // Start the packager before executing the React-Native command
104 Log.logMessage("Attempting to start the React Native packager");
105 return this.runStartPackagerCommandAndUpdateStatus().then(lambda);
106 }
107
108 /**
109 * Ensures that we are in a React Native project and then executes the operation
110 * Otherwise, displays an error message banner
111 * {operation} - a function that performs the expected operation
112 */
113 private executeCommandInContext(rnCommand: string, operation: () => Q.Promise<void> | void): Q.Promise<void> {
114 let reactNativeProjectHelper = new ReactNativeProjectHelper(vscode.workspace.rootPath);
115 return TelemetryHelper.generate("RNCommand", (generator) => {
116 generator.add("command", rnCommand, false);
117 return reactNativeProjectHelper.isReactNativeProject().then(isRNProject => {
118 generator.add("isRNProject", isRNProject, false);
119 if (isRNProject) {
120 // Bring the log channel to focus
121 Log.setFocusOnLogChannel();
122
123 // Execute the operation
124 return operation();
125 } else {
126 vscode.window.showErrorMessage("Current workspace is not a React Native project.");
127 }
128 });
129 });
130 }
131}
132