@@ -5,6 +5,15 @@ import { APP_FOLDER_NAME, APP_RESOURCES_FOLDER_NAME, TNS_MODULES_FOLDER_NAME } f
55import { HmrConstants } from "../../../common/constants" ;
66const isTextOrBinary = require ( 'istextorbinary' ) ;
77
8+ interface ISyncFilesOptions {
9+ filesToSync ?: string [ ] ;
10+ filesToRemove ?: string [ ] ;
11+ isInitialSync ?: boolean ;
12+ skipPrepare ?: boolean ;
13+ useHotModuleReload ?: boolean ;
14+ deviceId ?: string ;
15+ }
16+
817export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
918 private excludedFileExtensions = [ ".ts" , ".sass" , ".scss" , ".less" ] ;
1019 private excludedFiles = [ ".DS_Store" ] ;
@@ -53,24 +62,23 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
5362 const startSyncFilesTimeout = async ( platform : string ) => {
5463 await promise
5564 . then ( async ( ) => {
56- const projectData = this . $projectDataService . getProjectData ( data . projectDir ) ;
57- const platformData = this . $platformsData . getPlatformData ( platform , projectData ) ;
58- const currentHmrData = _ . cloneDeep ( hmrData ) ;
59- const filesToSync = _ . cloneDeep ( filesToSyncMap [ platform ] ) ;
60- promise = this . applyChanges ( platformData , projectData , filesToSync , { useHotModuleReload : data . appFilesUpdaterOptions . useHotModuleReload } ) ;
61- await promise ;
62-
63- if ( data . appFilesUpdaterOptions . useHotModuleReload && currentHmrData . hash ) {
64- const devices = _ . filter ( this . $previewSdkService . connectedDevices , { platform : platform . toLowerCase ( ) } ) ;
65-
66- await Promise . all ( _ . map ( devices , async ( previewDevice : Device ) => {
67- const status = await this . $hmrStatusService . getHmrStatus ( previewDevice . id , currentHmrData . hash ) ;
68- if ( status === HmrConstants . HMR_ERROR_STATUS ) {
69- await this . applyChanges ( platformData , projectData , currentHmrData . fallbackFiles [ platform ] , { useHotModuleReload : false } , previewDevice . id ) ;
70- }
71- } ) ) ;
72- }
73- } ) ;
65+ const currentHmrData = _ . cloneDeep ( hmrData ) ;
66+ const filesToSync = _ . cloneDeep ( filesToSyncMap [ platform ] ) ;
67+ // We don't need to prepare when webpack emits changed files. We just need to send a message to pubnub.
68+ promise = this . syncFilesForPlatformSafe ( data , platform , { filesToSync, skipPrepare : true , useHotModuleReload : data . appFilesUpdaterOptions . useHotModuleReload } ) ;
69+ await promise ;
70+
71+ if ( data . appFilesUpdaterOptions . useHotModuleReload && currentHmrData . hash ) {
72+ const devices = _ . filter ( this . $previewSdkService . connectedDevices , { platform : platform . toLowerCase ( ) } ) ;
73+
74+ await Promise . all ( _ . map ( devices , async ( previewDevice : Device ) => {
75+ const status = await this . $hmrStatusService . getHmrStatus ( previewDevice . id , currentHmrData . hash ) ;
76+ if ( status === HmrConstants . HMR_ERROR_STATUS ) {
77+ await this . syncFilesForPlatformSafe ( data , platform , { filesToSync : currentHmrData . fallbackFiles [ platform ] , useHotModuleReload : false , deviceId : previewDevice . id } ) ;
78+ }
79+ } ) ) ;
80+ }
81+ } ) ;
7482 filesToSyncMap [ platform ] = [ ] ;
7583 } ;
7684 await this . $hooksService . executeBeforeHooks ( "preview-sync" , {
@@ -88,13 +96,12 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
8896 }
8997 } ) ;
9098 await this . $previewAppPluginsService . comparePluginsOnDevice ( data , device ) ;
91- const payloads = await this . syncFilesForPlatformSafe ( data , device . platform ) ;
92- payloads . deviceId = device . id ;
99+ const payloads = await this . syncFilesForPlatformSafe ( data , device . platform , { isInitialSync : true , useHotModuleReload : data . appFilesUpdaterOptions . useHotModuleReload } ) ;
93100 return payloads ;
94101 }
95102
96- public async syncFiles ( data : IPreviewAppLiveSyncData , files ? : string [ ] ) : Promise < void > {
97- this . showWarningsForNativeFiles ( files ) ;
103+ public async syncFiles ( data : IPreviewAppLiveSyncData , filesToSync : string [ ] , filesToRemove : string [ ] ) : Promise < void > {
104+ this . showWarningsForNativeFiles ( filesToSync ) ;
98105
99106 for ( const device of this . $previewSdkService . connectedDevices ) {
100107 await this . $previewAppPluginsService . comparePluginsOnDevice ( data , device ) ;
@@ -106,87 +113,64 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
106113 . value ( ) ;
107114
108115 for ( const platform of platforms ) {
109- await this . syncFilesForPlatformSafe ( data , platform , files ) ;
116+ await this . syncFilesForPlatformSafe ( data , platform , { filesToSync , filesToRemove , useHotModuleReload : data . appFilesUpdaterOptions . useHotModuleReload } ) ;
110117 }
111118 }
112119
113120 public async stopLiveSync ( ) : Promise < void > {
114121 this . $previewSdkService . stop ( ) ;
115122 }
116123
117- private async syncFilesForPlatformSafe ( data : IPreviewAppLiveSyncData , platform : string , files ?: string [ ] ) : Promise < FilesPayload > {
124+ private async syncFilesForPlatformSafe ( data : IPreviewAppLiveSyncData , platform : string , opts ?: ISyncFilesOptions ) : Promise < FilesPayload > {
118125 this . $logger . info ( `Start syncing changes for platform ${ platform } .` ) ;
119126
127+ opts = opts || { } ;
128+ let payloads = null ;
129+
120130 try {
121131 const { appFilesUpdaterOptions, env, projectDir } = data ;
122132 const projectData = this . $projectDataService . getProjectData ( projectDir ) ;
123133 const platformData = this . $platformsData . getPlatformData ( platform , projectData ) ;
124- await this . preparePlatform ( platform , appFilesUpdaterOptions , env , projectData ) ;
125134
126- let result : FilesPayload = null ;
127- if ( files && files . length ) {
128- result = await this . applyChanges ( platformData , projectData , files , { useHotModuleReload : data . appFilesUpdaterOptions . useHotModuleReload } ) ;
129- this . $logger . info ( `Successfully synced ${ result . files . map ( filePayload => filePayload . file . yellow ) } for platform ${ platform } .` ) ;
130- } else {
131- const hmrMode = data . appFilesUpdaterOptions . useHotModuleReload ? 1 : 0 ;
132- result = await this . getFilesPayload ( platformData , projectData , hmrMode ) ;
135+ if ( ! opts . skipPrepare ) {
136+ await this . preparePlatform ( platform , appFilesUpdaterOptions , env , projectData ) ;
137+ }
138+
139+ if ( opts . isInitialSync ) {
140+ const platformsAppFolderPath = path . join ( platformData . appDestinationDirectoryPath , APP_FOLDER_NAME ) ;
141+ opts . filesToSync = this . $projectFilesManager . getProjectFiles ( platformsAppFolderPath ) ;
142+ payloads = this . getFilesPayload ( platformData , projectData , opts ) ;
133143 this . $logger . info ( `Successfully synced changes for platform ${ platform } .` ) ;
144+ } else {
145+ opts . filesToSync = _ . map ( opts . filesToSync , file => this . $projectFilesProvider . mapFilePath ( file , platformData . normalizedPlatformName , projectData ) ) ;
146+ payloads = this . getFilesPayload ( platformData , projectData , opts ) ;
147+ await this . $previewSdkService . applyChanges ( payloads ) ;
148+ this . $logger . info ( `Successfully synced ${ payloads . files . map ( filePayload => filePayload . file . yellow ) } for platform ${ platform } .` ) ;
134149 }
135150
136- return result ;
151+ return payloads ;
137152 } catch ( err ) {
138153 this . $logger . warn ( `Unable to apply changes for platform ${ platform } . Error is: ${ err } , ${ JSON . stringify ( err , null , 2 ) } .` ) ;
139154 }
140155 }
141156
142- private async applyChanges ( platformData : IPlatformData , projectData : IProjectData , files : string [ ] , { useHotModuleReload } : { useHotModuleReload : Boolean } , deviceId ?: string ) : Promise < FilesPayload > {
143- const hmrMode = useHotModuleReload ? 1 : 0 ;
144- const payloads = this . getFilesPayload ( platformData , projectData , hmrMode , _ ( files ) . uniq ( ) . value ( ) , deviceId ) ;
145- await this . $previewSdkService . applyChanges ( payloads ) ;
146-
147- return payloads ;
148- }
149-
150- private getFilesPayload ( platformData : IPlatformData , projectData : IProjectData , hmrMode : number , files ?: string [ ] , deviceId ?: string ) : FilesPayload {
151- const platformsAppFolderPath = path . join ( platformData . appDestinationDirectoryPath , APP_FOLDER_NAME ) ;
152-
153- if ( files && files . length ) {
154- files = files . map ( file => this . $projectFilesProvider . mapFilePath ( file , platformData . normalizedPlatformName , projectData ) ) ;
155- } else {
156- files = this . $projectFilesManager . getProjectFiles ( platformsAppFolderPath ) ;
157- }
157+ private getFilesPayload ( platformData : IPlatformData , projectData : IProjectData , opts ?: ISyncFilesOptions ) : FilesPayload {
158+ const { filesToSync, filesToRemove, deviceId } = opts ;
158159
159- const filesToTransfer = files
160+ const filesToTransfer = filesToSync
160161 . filter ( file => file . indexOf ( TNS_MODULES_FOLDER_NAME ) === - 1 )
161162 . filter ( file => file . indexOf ( APP_RESOURCES_FOLDER_NAME ) === - 1 )
162163 . filter ( file => ! _ . includes ( this . excludedFiles , path . basename ( file ) ) )
163164 . filter ( file => ! _ . includes ( this . excludedFileExtensions , path . extname ( file ) ) ) ;
164165
165166 this . $logger . trace ( `Transferring ${ filesToTransfer . join ( "\n" ) } .` ) ;
166167
167- const payloads = filesToTransfer
168- . map ( file => {
169- const projectFileInfo = this . $projectFilesProvider . getProjectFileInfo ( file , platformData . normalizedPlatformName , null ) ;
170- const relativePath = path . relative ( platformsAppFolderPath , file ) ;
171- const filePayload : FilePayload = {
172- event : PreviewSdkEventNames . CHANGE_EVENT_NAME ,
173- file : path . join ( path . dirname ( relativePath ) , projectFileInfo . onDeviceFileName ) ,
174- binary : isTextOrBinary . isBinarySync ( file ) ,
175- fileContents : ""
176- } ;
177-
178- if ( filePayload . binary ) {
179- const bitmap = < string > this . $fs . readFile ( file ) ;
180- const base64 = Buffer . from ( bitmap ) . toString ( 'base64' ) ;
181- filePayload . fileContents = base64 ;
182- } else {
183- filePayload . fileContents = this . $fs . readText ( path . join ( path . dirname ( projectFileInfo . filePath ) , projectFileInfo . onDeviceFileName ) ) ;
184- }
185-
186- return filePayload ;
187- } ) ;
188-
189- return { files : payloads , platform : platformData . normalizedPlatformName . toLowerCase ( ) , hmrMode, deviceId} ;
168+ const payloadsToSync = filesToTransfer . map ( file => this . createFilePayload ( file , platformData , projectData , PreviewSdkEventNames . CHANGE_EVENT_NAME ) ) ;
169+ const payloadsToRemove = _ . map ( filesToRemove , file => this . createFilePayload ( file , platformData , projectData , PreviewSdkEventNames . UNLINK_EVENT_NAME ) ) ;
170+ const payloads = payloadsToSync . concat ( payloadsToRemove ) ;
171+
172+ const hmrMode = opts . useHotModuleReload ? 1 : 0 ;
173+ return { files : payloads , platform : platformData . normalizedPlatformName . toLowerCase ( ) , hmrMode, deviceId } ;
190174 }
191175
192176 private async preparePlatform ( platform : string , appFilesUpdaterOptions : IAppFilesUpdaterOptions , env : Object , projectData : IProjectData ) : Promise < void > {
@@ -211,5 +195,36 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
211195 _ . filter ( files , file => file . indexOf ( APP_RESOURCES_FOLDER_NAME ) > - 1 )
212196 . forEach ( file => this . $logger . warn ( `Unable to apply changes from ${ APP_RESOURCES_FOLDER_NAME } folder. You need to build your application in order to make changes in ${ APP_RESOURCES_FOLDER_NAME } folder.` ) ) ;
213197 }
198+
199+ private createFilePayload ( file : string , platformData : IPlatformData , projectData : IProjectData , event : string ) : FilePayload {
200+ const projectFileInfo = this . $projectFilesProvider . getProjectFileInfo ( file , platformData . normalizedPlatformName , null ) ;
201+ const binary = isTextOrBinary . isBinarySync ( file ) ;
202+ let fileContents = "" ;
203+ let filePath = "" ;
204+
205+ if ( event === PreviewSdkEventNames . CHANGE_EVENT_NAME ) {
206+ const relativePath = path . relative ( path . join ( platformData . appDestinationDirectoryPath , APP_FOLDER_NAME ) , file ) ;
207+ filePath = path . join ( path . dirname ( relativePath ) , projectFileInfo . onDeviceFileName ) ;
208+
209+ if ( binary ) {
210+ const bitmap = < string > this . $fs . readFile ( file ) ;
211+ const base64 = Buffer . from ( bitmap ) . toString ( 'base64' ) ;
212+ fileContents = base64 ;
213+ } else {
214+ fileContents = this . $fs . readText ( path . join ( path . dirname ( projectFileInfo . filePath ) , projectFileInfo . onDeviceFileName ) ) ;
215+ }
216+ } else if ( event === PreviewSdkEventNames . UNLINK_EVENT_NAME ) {
217+ filePath = path . relative ( path . join ( projectData . projectDir , APP_FOLDER_NAME ) , file ) ;
218+ }
219+
220+ const filePayload = {
221+ event,
222+ file : filePath ,
223+ binary,
224+ fileContents
225+ } ;
226+
227+ return filePayload ;
228+ }
214229}
215230$injector . register ( "previewAppLiveSyncService" , PreviewAppLiveSyncService ) ;
0 commit comments