diff --git a/lib/bootstrap.ts b/lib/bootstrap.ts index 447d76ac0f..c66924ab9f 100644 --- a/lib/bootstrap.ts +++ b/lib/bootstrap.ts @@ -223,4 +223,6 @@ $injector.require("applePortalSessionService", "./services/apple-portal/apple-po $injector.require("applePortalCookieService", "./services/apple-portal/apple-portal-cookie-service"); $injector.require("applePortalApplicationService", "./services/apple-portal/apple-portal-application-service"); +$injector.require("watchIgnoreListService", "./services/watch-ignore-list-service"); + $injector.requirePublicClass("initializeService", "./services/initialize-service"); diff --git a/lib/controllers/prepare-controller.ts b/lib/controllers/prepare-controller.ts index 03febd68ef..3598f6da46 100644 --- a/lib/controllers/prepare-controller.ts +++ b/lib/controllers/prepare-controller.ts @@ -25,7 +25,8 @@ export class PrepareController extends EventEmitter { private $prepareNativePlatformService: IPrepareNativePlatformService, private $projectChangesService: IProjectChangesService, private $projectDataService: IProjectDataService, - private $webpackCompilerService: IWebpackCompilerService + private $webpackCompilerService: IWebpackCompilerService, + private $watchIgnoreListService: IWatchIgnoreListService ) { super(); } @performanceLog() @@ -131,8 +132,12 @@ export class PrepareController extends EventEmitter { const watcher = choki.watch(patterns, watcherOptions) .on("all", async (event: string, filePath: string) => { filePath = path.join(projectData.projectDir, filePath); - this.$logger.trace(`Chokidar raised event ${event} for ${filePath}.`); - this.emitPrepareEvent({ files: [], hasOnlyHotUpdateFiles: false, hmrData: null, hasNativeChanges: true, platform: platformData.platformNameLowerCase }); + if (this.$watchIgnoreListService.isFileInIgnoreList(filePath)) { + this.$watchIgnoreListService.removeFileFromIgnoreList(filePath); + } else { + this.$logger.info(`Chokidar raised event ${event} for ${filePath}.`); + this.emitPrepareEvent({ files: [], hasOnlyHotUpdateFiles: false, hmrData: null, hasNativeChanges: true, platform: platformData.platformNameLowerCase }); + } }); this.watchersData[projectData.projectDir][platformData.platformNameLowerCase].nativeFilesWatcher = watcher; diff --git a/lib/controllers/run-controller.ts b/lib/controllers/run-controller.ts index d85e2f5df2..1351084f8b 100644 --- a/lib/controllers/run-controller.ts +++ b/lib/controllers/run-controller.ts @@ -4,8 +4,6 @@ import { cache, performanceLog } from "../common/decorators"; import { EventEmitter } from "events"; export class RunController extends EventEmitter implements IRunController { - private rebuiltInformation: IDictionary<{ packageFilePath: string, platform: string, isEmulator: boolean }> = { }; - constructor( protected $analyticsService: IAnalyticsService, private $buildController: IBuildController, @@ -246,7 +244,7 @@ export class RunController extends EventEmitter implements IRunController { } private async syncInitialDataOnDevices(projectData: IProjectData, liveSyncInfo: ILiveSyncInfo, deviceDescriptors: ILiveSyncDeviceDescriptor[]): Promise { - this.rebuiltInformation = {}; + const rebuiltInformation: IDictionary<{ packageFilePath: string, platform: string, isEmulator: boolean }> = { }; const deviceAction = async (device: Mobile.IDevice) => { const deviceDescriptor = _.find(deviceDescriptors, dd => dd.identifier === device.deviceInfo.identifier); @@ -267,14 +265,14 @@ export class RunController extends EventEmitter implements IRunController { // Case where we have three devices attached, a change that requires build is found, // we'll rebuild the app only for the first device, but we should install new package on all three devices. - if (this.rebuiltInformation[platformData.platformNameLowerCase] && (this.$mobileHelper.isAndroidPlatform(platformData.platformNameLowerCase) || this.rebuiltInformation[platformData.platformNameLowerCase].isEmulator === device.isEmulator)) { - packageFilePath = this.rebuiltInformation[platformData.platformNameLowerCase].packageFilePath; + if (rebuiltInformation[platformData.platformNameLowerCase] && (this.$mobileHelper.isAndroidPlatform(platformData.platformNameLowerCase) || rebuiltInformation[platformData.platformNameLowerCase].isEmulator === device.isEmulator)) { + packageFilePath = rebuiltInformation[platformData.platformNameLowerCase].packageFilePath; await this.$deviceInstallAppService.installOnDevice(device, buildData, packageFilePath); } else { const shouldBuild = prepareResultData.hasNativeChanges || await this.$buildController.shouldBuild(buildData); if (shouldBuild) { packageFilePath = await deviceDescriptor.buildAction(); - this.rebuiltInformation[platformData.platformNameLowerCase] = { isEmulator: device.isEmulator, platform: platformData.platformNameLowerCase, packageFilePath }; + rebuiltInformation[platformData.platformNameLowerCase] = { isEmulator: device.isEmulator, platform: platformData.platformNameLowerCase, packageFilePath }; } else { await this.$analyticsService.trackEventActionInGoogleAnalytics({ action: TrackActionNames.LiveSync, @@ -315,7 +313,7 @@ export class RunController extends EventEmitter implements IRunController { } private async syncChangedDataOnDevices(data: IFilesChangeEventData, projectData: IProjectData, liveSyncInfo: ILiveSyncInfo, deviceDescriptors: ILiveSyncDeviceDescriptor[]): Promise { - this.rebuiltInformation = {}; + const rebuiltInformation: IDictionary<{ packageFilePath: string, platform: string, isEmulator: boolean }> = { }; const deviceAction = async (device: Mobile.IDevice) => { const deviceDescriptor = _.find(deviceDescriptors, dd => dd.identifier === device.deviceInfo.identifier); @@ -343,14 +341,14 @@ export class RunController extends EventEmitter implements IRunController { const deviceAppData = await platformLiveSyncService.getAppData(_.merge({ device, watch: true }, watchInfo)); if (data.hasNativeChanges) { - const rebuiltInfo = this.rebuiltInformation[platformData.platformNameLowerCase] && (this.$mobileHelper.isAndroidPlatform(platformData.platformNameLowerCase) || this.rebuiltInformation[platformData.platformNameLowerCase].isEmulator === device.isEmulator); + const rebuiltInfo = rebuiltInformation[platformData.platformNameLowerCase] && (this.$mobileHelper.isAndroidPlatform(platformData.platformNameLowerCase) || rebuiltInformation[platformData.platformNameLowerCase].isEmulator === device.isEmulator); if (!rebuiltInfo) { await this.$prepareNativePlatformService.prepareNativePlatform(platformData, projectData, prepareData); await deviceDescriptor.buildAction(); - this.rebuiltInformation[platformData.platformNameLowerCase] = { isEmulator: device.isEmulator, platform: platformData.platformNameLowerCase, packageFilePath: null }; + rebuiltInformation[platformData.platformNameLowerCase] = { isEmulator: device.isEmulator, platform: platformData.platformNameLowerCase, packageFilePath: null }; } - await this.$deviceInstallAppService.installOnDevice(device, deviceDescriptor.buildData, this.rebuiltInformation[platformData.platformNameLowerCase].packageFilePath); + await this.$deviceInstallAppService.installOnDevice(device, deviceDescriptor.buildData, rebuiltInformation[platformData.platformNameLowerCase].packageFilePath); await platformLiveSyncService.syncAfterInstall(device, watchInfo); await platformLiveSyncService.restartApplication(projectData, { deviceAppData, modifiedFilesData: [], isFullSync: false, useHotModuleReload: liveSyncInfo.useHotModuleReload }); } else { diff --git a/lib/declarations.d.ts b/lib/declarations.d.ts index 7c11063614..eed7ccdcf7 100644 --- a/lib/declarations.d.ts +++ b/lib/declarations.d.ts @@ -1049,4 +1049,10 @@ interface IPlatformCommandHelper { getAvailablePlatforms(projectData: IProjectData): string[]; getPreparedPlatforms(projectData: IProjectData): string[]; getCurrentPlatformVersion(platform: string, projectData: IProjectData): string; +} + +interface IWatchIgnoreListService { + addFileToIgnoreList(filePath: string): void; + removeFileFromIgnoreList(filePath: string): void; + isFileInIgnoreList(filePath: string): boolean; } \ No newline at end of file diff --git a/lib/services/android-plugin-build-service.ts b/lib/services/android-plugin-build-service.ts index 64ea547406..88f935cd65 100644 --- a/lib/services/android-plugin-build-service.ts +++ b/lib/services/android-plugin-build-service.ts @@ -20,7 +20,8 @@ export class AndroidPluginBuildService implements IAndroidPluginBuildService { private $errors: IErrors, private $filesHashService: IFilesHashService, public $hooksService: IHooksService, - private $injector: IInjector + private $injector: IInjector, + private $watchIgnoreListService: IWatchIgnoreListService ) { } private static MANIFEST_ROOT = { @@ -189,6 +190,7 @@ export class AndroidPluginBuildService implements IAndroidPluginBuildService { this.copySourceSetDirectories(androidSourceDirectories, pluginTempMainSrcDir); await this.setupGradle(pluginTempDir, options.platformsAndroidDirPath, options.projectDir); await this.buildPlugin({ pluginDir: pluginTempDir, pluginName: options.pluginName }); + this.$watchIgnoreListService.addFileToIgnoreList(path.join(options.aarOutputDir, `${shortPluginName}.aar`)); this.copyAar(shortPluginName, pluginTempDir, options.aarOutputDir); this.writePluginHashInfo(pluginSourceFileHashesInfo, pluginTempDir); } diff --git a/lib/services/watch-ignore-list-service.ts b/lib/services/watch-ignore-list-service.ts new file mode 100644 index 0000000000..aa69c75e98 --- /dev/null +++ b/lib/services/watch-ignore-list-service.ts @@ -0,0 +1,16 @@ +export class WatchIgnoreListService implements IWatchIgnoreListService { + private ignoreMap: IDictionary = {}; + + public addFileToIgnoreList(filePath: string): void { + this.ignoreMap[filePath] = true; + } + + public removeFileFromIgnoreList(filePath: string): void { + this.ignoreMap[filePath] = false; + } + + public isFileInIgnoreList(filePath: string): boolean { + return !!this.ignoreMap[filePath]; + } +} +$injector.register("watchIgnoreListService", WatchIgnoreListService); diff --git a/test/controllers/prepare-controller.ts b/test/controllers/prepare-controller.ts index 4f056804ed..ef0b4a0fd0 100644 --- a/test/controllers/prepare-controller.ts +++ b/test/controllers/prepare-controller.ts @@ -49,6 +49,11 @@ function createTestInjector(data: { hasNativeChanges: boolean }): IInjector { getProductionDependencies: () => ([]) }); + injector.register("watchIgnoreListService", { + addFileToIgnoreList: () => ({}), + isFileInIgnoreList: () => false + }); + const prepareController: PrepareController = injector.resolve("prepareController"); prepareController.emit = (eventName: string, eventData: any) => { emittedEventNames.push(eventName); diff --git a/test/services/android-plugin-build-service.ts b/test/services/android-plugin-build-service.ts index 962a0cdcd0..b920e2ab70 100644 --- a/test/services/android-plugin-build-service.ts +++ b/test/services/android-plugin-build-service.ts @@ -75,6 +75,10 @@ describe('androidPluginBuildService', () => { hasChangesInShasums: (oldHashes: IStringDictionary, newHashes: IStringDictionary): boolean => !!options.hasChangesInShasums }); + testInjector.register("watchIgnoreListService", { + addFileToIgnoreList: () => ({}) + }); + fs = testInjector.resolve("fs"); androidBuildPluginService = testInjector.resolve(AndroidPluginBuildService); }