@@ -4,6 +4,7 @@ import { cache, performanceLog } from "../common/decorators";
44import { EventEmitter } from "events" ;
55
66export class RunController extends EventEmitter implements IRunController {
7+ private rebuiltInformation : IDictionary < any > = { } ;
78
89 constructor (
910 protected $analyticsService : IAnalyticsService ,
@@ -236,6 +237,8 @@ export class RunController extends EventEmitter implements IRunController {
236237 }
237238
238239 private async syncInitialDataOnDevices ( projectData : IProjectData , liveSyncInfo : ILiveSyncInfo , deviceDescriptors : ILiveSyncDeviceDescriptor [ ] ) : Promise < void > {
240+ this . rebuiltInformation = { } ;
241+
239242 const deviceAction = async ( device : Mobile . IDevice ) => {
240243 const deviceDescriptor = _ . find ( deviceDescriptors , dd => dd . identifier === device . deviceInfo . identifier ) ;
241244 const platformData = this . $platformsDataService . getPlatformData ( device . deviceInfo . platform , projectData ) ;
@@ -245,18 +248,27 @@ export class RunController extends EventEmitter implements IRunController {
245248
246249 try {
247250 let packageFilePath : string = null ;
248- const shouldBuild = prepareResultData . hasNativeChanges || await this . $buildController . shouldBuild ( buildData ) ;
249- if ( shouldBuild ) {
250- packageFilePath = await deviceDescriptor . buildAction ( ) ;
251+
252+ // Case where we have three devices attached, a change that requires build is found,
253+ // we'll rebuild the app only for the first device, but we should install new package on all three devices.
254+ if ( this . rebuiltInformation [ platformData . platformNameLowerCase ] && ( this . $mobileHelper . isAndroidPlatform ( platformData . platformNameLowerCase ) || this . rebuiltInformation [ platformData . platformNameLowerCase ] . isEmulator === device . isEmulator ) ) {
255+ packageFilePath = this . rebuiltInformation [ platformData . platformNameLowerCase ] . packageFilePath ;
256+ await this . $deviceInstallAppService . installOnDevice ( device , buildData , packageFilePath ) ;
251257 } else {
252- await this . $analyticsService . trackEventActionInGoogleAnalytics ( {
253- action : TrackActionNames . LiveSync ,
254- device,
255- projectDir : projectData . projectDir
256- } ) ;
257- }
258+ const shouldBuild = prepareResultData . hasNativeChanges || await this . $buildController . shouldBuild ( buildData ) ;
259+ if ( shouldBuild ) {
260+ packageFilePath = await deviceDescriptor . buildAction ( ) ;
261+ this . rebuiltInformation [ platformData . platformNameLowerCase ] = { isEmulator : device . isEmulator , platform : platformData . platformNameLowerCase , packageFilePath } ;
262+ } else {
263+ await this . $analyticsService . trackEventActionInGoogleAnalytics ( {
264+ action : TrackActionNames . LiveSync ,
265+ device,
266+ projectDir : projectData . projectDir
267+ } ) ;
268+ }
258269
259- await this . $deviceInstallAppService . installOnDeviceIfNeeded ( device , buildData , packageFilePath ) ;
270+ await this . $deviceInstallAppService . installOnDeviceIfNeeded ( device , buildData , packageFilePath ) ;
271+ }
260272
261273 const platformLiveSyncService = this . $liveSyncServiceResolver . resolveLiveSyncService ( platformData . platformNameLowerCase ) ;
262274 const { force, useHotModuleReload, skipWatcher } = liveSyncInfo ;
@@ -295,15 +307,19 @@ export class RunController extends EventEmitter implements IRunController {
295307 }
296308
297309 private async syncChangedDataOnDevices ( data : IFilesChangeEventData , projectData : IProjectData , liveSyncInfo : ILiveSyncInfo , deviceDescriptors : ILiveSyncDeviceDescriptor [ ] ) : Promise < void > {
310+ this . rebuiltInformation = { } ;
311+
298312 const deviceAction = async ( device : Mobile . IDevice ) => {
299313 const deviceDescriptor = _ . find ( deviceDescriptors , dd => dd . identifier === device . deviceInfo . identifier ) ;
300314 const platformData = this . $platformsDataService . getPlatformData ( data . platform , projectData ) ;
301315 const prepareData = this . $prepareDataService . getPrepareData ( projectData . projectDir , data . platform , { ...liveSyncInfo , watch : ! liveSyncInfo . skipWatcher } ) ;
302316
303317 try {
304- if ( data . hasNativeChanges ) {
318+ const rebuiltInfo = this . rebuiltInformation [ platformData . platformNameLowerCase ] && ( this . $mobileHelper . isAndroidPlatform ( platformData . platformNameLowerCase ) || this . rebuiltInformation [ platformData . platformNameLowerCase ] . isEmulator === device . isEmulator ) ;
319+ if ( data . hasNativeChanges && ! rebuiltInfo ) {
305320 await this . $prepareNativePlatformService . prepareNativePlatform ( platformData , projectData , prepareData ) ;
306321 await deviceDescriptor . buildAction ( ) ;
322+ this . rebuiltInformation [ platformData . platformNameLowerCase ] = { isEmulator : device . isEmulator , platform : platformData . platformNameLowerCase , packageFilePath : null } ;
307323 }
308324
309325 const isInHMRMode = liveSyncInfo . useHotModuleReload && data . hmrData && data . hmrData . hash ;
0 commit comments