@@ -5,6 +5,15 @@ import { APP_FOLDER_NAME, APP_RESOURCES_FOLDER_NAME, TNS_MODULES_FOLDER_NAME } f
5
5
import { HmrConstants } from "../../../common/constants" ;
6
6
const isTextOrBinary = require ( 'istextorbinary' ) ;
7
7
8
+ interface ISyncFilesOptions {
9
+ filesToSync ?: string [ ] ;
10
+ filesToRemove ?: string [ ] ;
11
+ isInitialSync ?: boolean ;
12
+ skipPrepare ?: boolean ;
13
+ useHotModuleReload ?: boolean ;
14
+ deviceId ?: string ;
15
+ }
16
+
8
17
export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
9
18
private excludedFileExtensions = [ ".ts" , ".sass" , ".scss" , ".less" ] ;
10
19
private excludedFiles = [ ".DS_Store" ] ;
@@ -53,24 +62,23 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
53
62
const startSyncFilesTimeout = async ( platform : string ) => {
54
63
await promise
55
64
. 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
+ } ) ;
74
82
filesToSyncMap [ platform ] = [ ] ;
75
83
} ;
76
84
await this . $hooksService . executeBeforeHooks ( "preview-sync" , {
@@ -88,13 +96,12 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
88
96
}
89
97
} ) ;
90
98
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 } ) ;
93
100
return payloads ;
94
101
}
95
102
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 ) ;
98
105
99
106
for ( const device of this . $previewSdkService . connectedDevices ) {
100
107
await this . $previewAppPluginsService . comparePluginsOnDevice ( data , device ) ;
@@ -106,87 +113,64 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
106
113
. value ( ) ;
107
114
108
115
for ( const platform of platforms ) {
109
- await this . syncFilesForPlatformSafe ( data , platform , files ) ;
116
+ await this . syncFilesForPlatformSafe ( data , platform , { filesToSync , filesToRemove , useHotModuleReload : data . appFilesUpdaterOptions . useHotModuleReload } ) ;
110
117
}
111
118
}
112
119
113
120
public async stopLiveSync ( ) : Promise < void > {
114
121
this . $previewSdkService . stop ( ) ;
115
122
}
116
123
117
- private async syncFilesForPlatformSafe ( data : IPreviewAppLiveSyncData , platform : string , files ?: string [ ] ) : Promise < FilesPayload > {
124
+ private async syncFilesForPlatformSafe ( data : IPreviewAppLiveSyncData , platform : string , opts ?: ISyncFilesOptions ) : Promise < FilesPayload > {
118
125
this . $logger . info ( `Start syncing changes for platform ${ platform } .` ) ;
119
126
127
+ opts = opts || { } ;
128
+ let payloads = null ;
129
+
120
130
try {
121
131
const { appFilesUpdaterOptions, env, projectDir } = data ;
122
132
const projectData = this . $projectDataService . getProjectData ( projectDir ) ;
123
133
const platformData = this . $platformsData . getPlatformData ( platform , projectData ) ;
124
- await this . preparePlatform ( platform , appFilesUpdaterOptions , env , projectData ) ;
125
134
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 ) ;
133
143
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 } .` ) ;
134
149
}
135
150
136
- return result ;
151
+ return payloads ;
137
152
} catch ( err ) {
138
153
this . $logger . warn ( `Unable to apply changes for platform ${ platform } . Error is: ${ err } , ${ JSON . stringify ( err , null , 2 ) } .` ) ;
139
154
}
140
155
}
141
156
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 ;
158
159
159
- const filesToTransfer = files
160
+ const filesToTransfer = filesToSync
160
161
. filter ( file => file . indexOf ( TNS_MODULES_FOLDER_NAME ) === - 1 )
161
162
. filter ( file => file . indexOf ( APP_RESOURCES_FOLDER_NAME ) === - 1 )
162
163
. filter ( file => ! _ . includes ( this . excludedFiles , path . basename ( file ) ) )
163
164
. filter ( file => ! _ . includes ( this . excludedFileExtensions , path . extname ( file ) ) ) ;
164
165
165
166
this . $logger . trace ( `Transferring ${ filesToTransfer . join ( "\n" ) } .` ) ;
166
167
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 } ;
190
174
}
191
175
192
176
private async preparePlatform ( platform : string , appFilesUpdaterOptions : IAppFilesUpdaterOptions , env : Object , projectData : IProjectData ) : Promise < void > {
@@ -211,5 +195,36 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
211
195
_ . filter ( files , file => file . indexOf ( APP_RESOURCES_FOLDER_NAME ) > - 1 )
212
196
. 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.` ) ) ;
213
197
}
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
+ }
214
229
}
215
230
$injector . register ( "previewAppLiveSyncService" , PreviewAppLiveSyncService ) ;
0 commit comments