diff --git a/lib/bootstrap.ts b/lib/bootstrap.ts index adbc81da63..b6283ba8f9 100644 --- a/lib/bootstrap.ts +++ b/lib/bootstrap.ts @@ -135,7 +135,7 @@ $injector.require("previewAppLiveSyncService", "./services/livesync/playground/p $injector.require("previewAppPluginsService", "./services/livesync/playground/preview-app-plugins-service"); $injector.require("previewSdkService", "./services/livesync/playground/preview-sdk-service"); $injector.requirePublicClass("previewDevicesService", "./services/livesync/playground/devices/preview-devices-service"); -$injector.require("playgroundQrCodeGenerator", "./services/livesync/playground/qr-code-generator"); +$injector.requirePublic("previewQrCodeService", "./services/livesync/playground/preview-qr-code-service"); $injector.requirePublic("sysInfo", "./sys-info"); $injector.require("iOSNotificationService", "./services/ios-notification-service"); diff --git a/lib/commands/preview.ts b/lib/commands/preview.ts index 1926fcf8bf..bc42413b3f 100644 --- a/lib/commands/preview.ts +++ b/lib/commands/preview.ts @@ -8,7 +8,7 @@ export class PreviewCommand implements ICommand { private $networkConnectivityValidator: INetworkConnectivityValidator, private $projectData: IProjectData, private $options: IOptions, - private $playgroundQrCodeGenerator: IPlaygroundQrCodeGenerator) { } + private $previewQrCodeService: IPreviewQrCodeService) { } public async execute(): Promise { await this.$liveSyncService.liveSync([], { @@ -24,7 +24,7 @@ export class PreviewCommand implements ICommand { useHotModuleReload: this.$options.hmr }); - await this.$playgroundQrCodeGenerator.generateQrCode({ useHotModuleReload: this.$options.hmr, link: this.$options.link }); + await this.$previewQrCodeService.printLiveSyncQrCode({ useHotModuleReload: this.$options.hmr, link: this.$options.link }); } public async canExecute(args: string[]): Promise { diff --git a/lib/common/declarations.d.ts b/lib/common/declarations.d.ts index 8aedd1092c..06bd4e3061 100644 --- a/lib/common/declarations.d.ts +++ b/lib/common/declarations.d.ts @@ -969,6 +969,21 @@ interface IQrCodeGenerator { generateDataUri(data: string): Promise; } +interface IQrCodeImageData { + /** + * The original URL used for generating QR code image. + */ + originalUrl: string; + /** + * The shorten URL used for generating QR code image. + */ + shortenUrl: string; + /** + * Base64 encoded data used for generating QR code image. + */ + imageData: string; +} + interface IDynamicHelpProvider { /** * Checks if current project's framework is one of the specified as arguments. diff --git a/lib/definitions/preview-app-livesync.d.ts b/lib/definitions/preview-app-livesync.d.ts index 23bcbdb491..bbee82aa56 100644 --- a/lib/definitions/preview-app-livesync.d.ts +++ b/lib/definitions/preview-app-livesync.d.ts @@ -22,11 +22,16 @@ declare global { getExternalPlugins(device: Device): string[]; } - interface IPlaygroundQrCodeGenerator { - generateQrCode(options: IGenerateQrCodeOptions): Promise; + interface IPreviewQrCodeService { + getPlaygroundAppQrCode(options?: IPlaygroundAppQrCodeOptions): Promise>; + printLiveSyncQrCode(options: IPrintLiveSyncOptions): Promise; } - interface IGenerateQrCodeOptions extends IHasUseHotModuleReloadOption { + interface IPlaygroundAppQrCodeOptions { + platform?: string; + } + + interface IPrintLiveSyncOptions extends IHasUseHotModuleReloadOption { /** * If set to true, a link will be shown on console instead of QR code * Default value is false. diff --git a/lib/services/livesync/playground/preview-qr-code-service.ts b/lib/services/livesync/playground/preview-qr-code-service.ts new file mode 100644 index 0000000000..3421fe4903 --- /dev/null +++ b/lib/services/livesync/playground/preview-qr-code-service.ts @@ -0,0 +1,77 @@ +import * as util from "util"; +import { EOL } from "os"; +import { PlaygroundStoreUrls } from "./preview-app-constants"; +import { exported } from "../../../common/decorators"; + +export class PreviewQrCodeService implements IPreviewQrCodeService { + constructor( + private $config: IConfiguration, + private $httpClient: Server.IHttpClient, + private $logger: ILogger, + private $mobileHelper: Mobile.IMobileHelper, + private $previewSdkService: IPreviewSdkService, + private $qrCodeTerminalService: IQrCodeTerminalService, + private $qr: IQrCodeGenerator + ) { } + + @exported("previewQrCodeService") + public async getPlaygroundAppQrCode(options?: IPlaygroundAppQrCodeOptions): Promise> { + const result = Object.create(null); + + if (!options || !options.platform || this.$mobileHelper.isAndroidPlatform(options.platform)) { + result.android = await this.getQrCodeImageData(PlaygroundStoreUrls.GOOGLE_PLAY_URL); + } + + if (!options || !options.platform || this.$mobileHelper.isiOSPlatform(options.platform)) { + result.ios = await this.getQrCodeImageData(PlaygroundStoreUrls.APP_STORE_URL); + } + + return result; + } + + public async printLiveSyncQrCode(options: IPrintLiveSyncOptions): Promise { + const qrCodeUrl = this.$previewSdkService.getQrCodeUrl(options); + const url = await this.getShortenUrl(qrCodeUrl); + + this.$logger.info(); + const message = `${EOL} Generating qrcode for url ${url}.`; + this.$logger.trace(message); + + if (options.link) { + this.$logger.printMarkdown(message); + } else { + this.$qrCodeTerminalService.generate(url); + + this.$logger.info(); + this.$logger.printMarkdown(`# Use \`NativeScript Playground app\` and scan the \`QR code\` above to preview the application on your device.`); + this.$logger.printMarkdown(` +To scan the QR code and deploy your app on a device, you need to have the \`NativeScript Playground app\`: + App Store (iOS): ${PlaygroundStoreUrls.APP_STORE_URL} + Google Play (Android): ${PlaygroundStoreUrls.GOOGLE_PLAY_URL}`); + } + } + + private async getShortenUrl(url: string): Promise { + const shortenUrlEndpoint = util.format(this.$config.SHORTEN_URL_ENDPOINT, encodeURIComponent(url)); + try { + const response = await this.$httpClient.httpRequest(shortenUrlEndpoint); + const responseBody = JSON.parse(response.body); + url = responseBody.shortURL || url; + } catch (e) { + // use the longUrl + } + + return url; + } + + private async getQrCodeImageData(url: string): Promise { + const shortenUrl = await this.getShortenUrl(url); + const imageData = await this.$qr.generateDataUri(shortenUrl); + return { + originalUrl: url, + shortenUrl, + imageData + }; + } +} +$injector.register("previewQrCodeService", PreviewQrCodeService); diff --git a/lib/services/livesync/playground/qr-code-generator.ts b/lib/services/livesync/playground/qr-code-generator.ts deleted file mode 100644 index cea5810478..0000000000 --- a/lib/services/livesync/playground/qr-code-generator.ts +++ /dev/null @@ -1,42 +0,0 @@ -import * as util from "util"; -import { EOL } from "os"; -import { PlaygroundStoreUrls } from "./preview-app-constants"; - -export class PlaygroundQrCodeGenerator implements IPlaygroundQrCodeGenerator { - constructor(private $previewSdkService: IPreviewSdkService, - private $httpClient: Server.IHttpClient, - private $qrCodeTerminalService: IQrCodeTerminalService, - private $config: IConfiguration, - private $logger: ILogger) { - } - - public async generateQrCode(options: IGenerateQrCodeOptions): Promise { - let url = this.$previewSdkService.getQrCodeUrl(options); - const shortenUrlEndpoint = util.format(this.$config.SHORTEN_URL_ENDPOINT, encodeURIComponent(url)); - try { - const response = await this.$httpClient.httpRequest(shortenUrlEndpoint); - const responseBody = JSON.parse(response.body); - url = responseBody.shortURL || url; - } catch (e) { - // use the longUrl - } - - this.$logger.info(); - const message = `${EOL} Generating qrcode for url ${url}.`; - this.$logger.trace(message); - - if (options.link) { - this.$logger.printMarkdown(message); - } else { - this.$qrCodeTerminalService.generate(url); - - this.$logger.info(); - this.$logger.printMarkdown(`# Use \`NativeScript Playground app\` and scan the \`QR code\` above to preview the application on your device.`); - this.$logger.printMarkdown(` -To scan the QR code and deploy your app on a device, you need to have the \`NativeScript Playground app\`: - App Store (iOS): ${PlaygroundStoreUrls.APP_STORE_URL} - Google Play (Android): ${PlaygroundStoreUrls.GOOGLE_PLAY_URL}`); - } - } -} -$injector.register("playgroundQrCodeGenerator", PlaygroundQrCodeGenerator); diff --git a/lib/services/platform-environment-requirements.ts b/lib/services/platform-environment-requirements.ts index 284a399006..4cbd86c4ad 100644 --- a/lib/services/platform-environment-requirements.ts +++ b/lib/services/platform-environment-requirements.ts @@ -13,7 +13,7 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ private $staticConfig: IStaticConfig, private $analyticsService: IAnalyticsService, private $injector: IInjector, - private $playgroundQrCodeGenerator: IPlaygroundQrCodeGenerator) { } + private $previewQrCodeService: IPreviewQrCodeService) { } @cache() private get $liveSyncService(): ILiveSyncService { @@ -194,7 +194,7 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ useHotModuleReload: options.hmr }); - await this.$playgroundQrCodeGenerator.generateQrCode({ useHotModuleReload: options.hmr, link: options.link }); + await this.$previewQrCodeService.printLiveSyncQrCode({ useHotModuleReload: options.hmr, link: options.link }); } } diff --git a/test/services/platform-environment-requirements.ts b/test/services/platform-environment-requirements.ts index dce5ab3806..5dab5825ff 100644 --- a/test/services/platform-environment-requirements.ts +++ b/test/services/platform-environment-requirements.ts @@ -28,7 +28,7 @@ function createTestInjector() { testInjector.register("platformEnvironmentRequirements", PlatformEnvironmentRequirements); testInjector.register("staticConfig", { SYS_REQUIREMENTS_LINK: "" }); testInjector.register("nativeScriptCloudExtensionService", {}); - testInjector.register("playgroundQrCodeGenerator", {}); + testInjector.register("previewQrCodeService", {}); return testInjector; }