diff --git a/docs/man_pages/project/configuration/open-android.md b/docs/man_pages/project/configuration/open-android.md new file mode 100644 index 0000000000..95453c9b4b --- /dev/null +++ b/docs/man_pages/project/configuration/open-android.md @@ -0,0 +1,27 @@ +<% if (isJekyll) { %>--- +title: ns open android +position: 10 +---<% } %> + +# ns open android + +### Description + +Opens the Android native project from the corresponding `platforms` directory. + +If the native project has not already been generated, the `prepare` command will be issued to generate the project, and the project will then be opened. + +### Commands + +Usage | Synopsis +------|------- +Open the project in Android Studio | `$ ns open android` + +<% if(isHtml) { %> + +### Related Commands + +Command | Description +----------|---------- +[prepare](prepare.html) | Copies common and relevant platform-specific content from the app directory to the subdirectory for the selected target platform in the platforms directory. +<% } %> \ No newline at end of file diff --git a/docs/man_pages/project/configuration/open-ios.md b/docs/man_pages/project/configuration/open-ios.md new file mode 100644 index 0000000000..7087dfb195 --- /dev/null +++ b/docs/man_pages/project/configuration/open-ios.md @@ -0,0 +1,31 @@ +<% if (isJekyll) { %>--- +title: ns open ios +position: 10 +---<% } %> + +# ns open ios + +### Description + +Opens the iOS native project from the corresponding `platforms` directory. + +If the native project has not already been generated, the `prepare` command will be issued to generate the project, and the project will then be opened. + +### Commands + +Usage | Synopsis +------|------- +Open the project in Xcode | `$ ns open ios` + +<% if(isHtml) { %> + +### Command Limitations + +* You can run `$ ns open ios` only on macOS systems. + +### Related Commands + +Command | Description +----------|---------- +[prepare](prepare.html) | Copies common and relevant platform-specific content from the app directory to the subdirectory for the selected target platform in the platforms directory. +<% } %> \ No newline at end of file diff --git a/docs/man_pages/project/configuration/open.md b/docs/man_pages/project/configuration/open.md new file mode 100644 index 0000000000..097cac0bcc --- /dev/null +++ b/docs/man_pages/project/configuration/open.md @@ -0,0 +1,36 @@ +<% if (isJekyll) { %>--- +title: ns open +position: 10 +---<% } %> + +# ns open + +### Description + +Opens the iOS/Android native project from the corresponding `platforms` directory. + +If the native project has not already been generated, the `prepare` command will be issued to generate the project, and the project will then be opened. + +### Commands + +Usage | Synopsis +------|------- +<% if((isConsole && isMacOS) || isHtml) { %>General | `$ ns open `<% } %><% if(isConsole && (isLinux || isWindows)) { %>General | `$ ns open android`<% } %> + +<% if(isMacOS) { %>### Arguments +`` is the target mobile platform for which you want to open the native project. You can set the following target platforms. +* `android` - Opens the Android project in Android Studio. +* `ios` - Opens native iOS project in Xcode.<% } %> + +<% if(isHtml) { %> + +### Command Limitations + +* You can run `$ ns open ios` only on macOS systems. + +### Related Commands + +Command | Description +----------|---------- +[prepare](prepare.html) | Copies common and relevant platform-specific content from the app directory to the subdirectory for the selected target platform in the platforms directory. +<% } %> \ No newline at end of file diff --git a/docs/man_pages/start.md b/docs/man_pages/start.md index 51b24d90ee..73277b326c 100644 --- a/docs/man_pages/start.md +++ b/docs/man_pages/start.md @@ -49,6 +49,7 @@ Command | Description [test ``](project/testing/test.html) | Runs the unit tests in your project on a connected physical or virtual device. [install](project/configuration/install.html) | Installs all platforms and dependencies described in the `package.json` file in the current directory. [plugin](lib-management/plugin.html) | Lets you manage the plugins for your project. +[open](project/configuration/open.md) | Opens the native project in Xcode/Android Studio. ## Publishing Commands Command | Description diff --git a/lib/key-commands/bootstrap.ts b/lib/key-commands/bootstrap.ts index 39175eda4c..955178e5a5 100644 --- a/lib/key-commands/bootstrap.ts +++ b/lib/key-commands/bootstrap.ts @@ -15,3 +15,5 @@ injector.requireKeyCommand("n", path); injector.requireKeyCommand(SpecialKeys.QuestionMark, path); injector.requireKeyCommand(SpecialKeys.CtrlC, path); +injector.requireCommand("open|ios", path); +injector.requireCommand("open|android", path); diff --git a/lib/key-commands/index.ts b/lib/key-commands/index.ts index 29daa9d6c3..f7887ffdba 100644 --- a/lib/key-commands/index.ts +++ b/lib/key-commands/index.ts @@ -3,7 +3,7 @@ import { platform as currentPlatform } from "os"; import * as path from "path"; import { color } from "../color"; import { PrepareCommand } from "../commands/prepare"; -import { IChildProcess } from "../common/declarations"; +import { IChildProcess, IXcodeSelectService } from "../common/declarations"; import { ICommand } from "../common/definitions/commands"; import { IKeyCommand, @@ -16,6 +16,8 @@ import { import { injector } from "../common/yok"; import { IProjectData } from "../definitions/project"; import { IStartService } from "../definitions/start-service"; +import { IOSProjectService } from "../services/ios-project-service"; +import { IOptions } from "../declarations"; export class A implements IKeyCommand { key: IValidKeyName = "a"; @@ -38,7 +40,7 @@ export class ShiftA implements IKeyCommand { platform: IKeyCommandPlatform = "Android"; description: string = "Open android project in Android Studio"; willBlockKeyCommandExecution: boolean = true; - + protected isInteractive: boolean = true; constructor( private $logger: ILogger, private $liveSyncCommandHelper: ILiveSyncCommandHelper, @@ -56,7 +58,9 @@ export class ShiftA implements IKeyCommand { "prepare" ) as PrepareCommand; await prepareCommand.execute([this.platform]); - process.stdin.resume(); + if (this.isInteractive) { + process.stdin.resume(); + } } const os = currentPlatform(); @@ -93,7 +97,11 @@ export class ShiftA implements IKeyCommand { return; } - this.$childProcess.exec(`"${studioPath}" "${androidDir}"`); + const child = this.$childProcess.spawn(studioPath, [androidDir], { + detached: true, + stdio: "ignore", + }); + child.unref(); } else if (os === "linux") { if (!fs.existsSync(`/usr/local/android-studio/bin/studio.sh`)) { this.$logger.error("Android Studio is not installed"); @@ -105,6 +113,22 @@ export class ShiftA implements IKeyCommand { } } } +export class OpenAndroidCommand extends ShiftA { + constructor( + $logger: ILogger, + $liveSyncCommandHelper: ILiveSyncCommandHelper, + $childProcess: IChildProcess, + $projectData: IProjectData, + private $options: IOptions + ) { + super($logger, $liveSyncCommandHelper, $childProcess, $projectData); + this.isInteractive = false; + } + async execute(): Promise { + this.$options.watch = false; + super.execute(); + } +} export class I implements IKeyCommand { key: IValidKeyName = "i"; @@ -127,40 +151,83 @@ export class ShiftI implements IKeyCommand { platform: IKeyCommandPlatform = "iOS"; description: string = "Open iOS project in Xcode"; willBlockKeyCommandExecution: boolean = true; + protected isInteractive: boolean = true; constructor( + private $iOSProjectService: IOSProjectService, private $logger: ILogger, private $childProcess: IChildProcess, - private $projectData: IProjectData + private $projectData: IProjectData, + private $xcodeSelectService: IXcodeSelectService, + private $xcodebuildArgsService: IXcodebuildArgsService ) {} async execute(): Promise { - this.$projectData.initializeProjectData(); - const iosDir = path.resolve(this.$projectData.platformsDir, "ios"); - - // TODO: reuse logic for resolving the xcode project file. - const xcprojectFile = path.resolve(iosDir); - - if (!fs.existsSync(iosDir)) { - const prepareCommand = injector.resolveCommand( - "prepare" - ) as PrepareCommand; - await prepareCommand.execute(["ios"]); - process.stdin.resume(); - } - const os = currentPlatform(); if (os === "darwin") { - // TODO: remove this, and just use "open path/to/ios/xcworkspace or xcproject". - if (!fs.existsSync("/Applications/Xcode.app")) { - this.$logger.error("Xcode is not installed"); - return; + this.$projectData.initializeProjectData(); + const iosDir = path.resolve(this.$projectData.platformsDir, "ios"); + + if (!fs.existsSync(iosDir)) { + const prepareCommand = injector.resolveCommand( + "prepare" + ) as PrepareCommand; + + await prepareCommand.execute(["ios"]); + if (this.isInteractive) { + process.stdin.resume(); + } } - this.$childProcess.exec(`open ${xcprojectFile}`); + const platformData = this.$iOSProjectService.getPlatformData( + this.$projectData + ); + const xcprojectFile = this.$xcodebuildArgsService.getXcodeProjectArgs( + platformData.projectRoot, + this.$projectData + )[1]; + + if (fs.existsSync(xcprojectFile)) { + this.$xcodeSelectService + .getDeveloperDirectoryPath() + .then(() => this.$childProcess.exec(`open ${xcprojectFile}`, {})) + .catch((e) => { + this.$logger.error(e.message); + }); + } else { + this.$logger.error(`Unable to open project file: ${xcprojectFile}`); + } + } else { + this.$logger.error("Opening a project in XCode requires macOS."); } } } +export class OpenIOSCommand extends ShiftI { + constructor( + $iOSProjectService: IOSProjectService, + $logger: ILogger, + $childProcess: IChildProcess, + $projectData: IProjectData, + $xcodeSelectService: IXcodeSelectService, + $xcodebuildArgsService: IXcodebuildArgsService, + private $options: IOptions + ) { + super( + $iOSProjectService, + $logger, + $childProcess, + $projectData, + $xcodeSelectService, + $xcodebuildArgsService + ); + this.isInteractive = false; + } + async execute(): Promise { + this.$options.watch = false; + super.execute(); + } +} + export class R implements IKeyCommand { key: IValidKeyName = "r"; platform: IKeyCommandPlatform = "all"; @@ -317,3 +384,6 @@ injector.registerKeyCommand("A", ShiftA); injector.registerKeyCommand("n", N); injector.registerKeyCommand(SpecialKeys.QuestionMark, QuestionMark); injector.registerKeyCommand(SpecialKeys.CtrlC, CtrlC); + +injector.registerCommand("open|ios", OpenIOSCommand); +injector.registerCommand("open|android", OpenAndroidCommand);