@@ -3,6 +3,7 @@ import * as React from 'react';
3
3
import { computed , observable , action , autorun , flow } from 'mobx' ;
4
4
import { observer , inject , disposeOnUnmount } from 'mobx-react' ;
5
5
6
+ import { delay } from '../../../util/promise' ;
6
7
import { styled } from '../../../styles' ;
7
8
8
9
import { Interceptor } from '../../../model/interception/interceptors' ;
@@ -160,9 +161,17 @@ class FridaConfig extends React.Component<{
160
161
) ?? [ ] ;
161
162
} . bind ( this ) ) ;
162
163
163
-
164
- @observable private inProgressHostIds : string [ ] = [ ] ;
165
164
@observable private inProgressTargetIds : string [ ] = [ ] ;
165
+ @observable private hostProgress : { [ hostId : string ] : number } = { } ;
166
+
167
+ @action
168
+ setHostProgress ( hostId : string , progress : number | undefined ) {
169
+ if ( progress === undefined ) {
170
+ delete this . hostProgress [ hostId ] ;
171
+ } else {
172
+ this . hostProgress [ hostId ] = progress ;
173
+ }
174
+ }
166
175
167
176
async componentDidMount ( ) {
168
177
if ( this . fridaHosts . length === 1 && this . fridaHosts [ 0 ] . state === 'available' ) {
@@ -209,30 +218,25 @@ class FridaConfig extends React.Component<{
209
218
}
210
219
211
220
@action . bound
212
- selectHost ( hostId : string ) {
221
+ async selectHost ( hostId : string ) {
213
222
const host = this . getHost ( hostId ) ;
214
223
215
224
if ( host ?. state === 'available' ) {
216
- this . selectedHostId = hostId ;
217
- this . searchInput = '' ;
218
- this . updateTargets ( ) ;
219
- } else if ( host ?. state === 'launch-required' ) {
220
- this . inProgressHostIds . push ( hostId ) ;
221
- this . props . activateInterceptor ( {
222
- action : 'launch' ,
223
- hostId
224
- } ) . finally ( action ( ( ) => {
225
- _ . pull ( this . inProgressHostIds , hostId ) ;
226
- } ) ) ;
225
+ this . viewHostTargets ( hostId ) ;
226
+ return ;
227
+ }
228
+
229
+ // Do nothing if the host is already busy:
230
+ if ( this . hostProgress [ hostId ] !== undefined ) return ;
231
+
232
+ this . hostProgress [ hostId ] = 10 ;
233
+
234
+ if ( host ?. state === 'launch-required' ) {
235
+ await this . launchInterceptor ( hostId ) ;
227
236
} else if ( host ?. state === 'setup-required' ) {
228
- this . inProgressHostIds . push ( hostId ) ;
229
- this . props . activateInterceptor ( {
230
- action : 'setup' ,
231
- hostId
232
- } ) . finally ( action ( ( ) => {
233
- _ . pull ( this . inProgressHostIds , hostId ) ;
234
- } ) ) ;
237
+ await this . setupInterceptor ( hostId ) ;
235
238
} else {
239
+ // Should probably never happen, but maybe in some race conditions
236
240
return ;
237
241
}
238
242
}
@@ -242,6 +246,62 @@ class FridaConfig extends React.Component<{
242
246
this . selectedHostId = undefined ;
243
247
}
244
248
249
+ @action
250
+ viewHostTargets ( hostId : string ) {
251
+ this . selectedHostId = hostId ;
252
+ this . searchInput = '' ;
253
+ this . updateTargets ( ) ;
254
+ }
255
+
256
+ async setupInterceptor ( hostId : string ) {
257
+ // Logarithmically move towards 75% while setup runs:
258
+ let interval = setInterval ( ( ) => {
259
+ const currentProgress = this . hostProgress [ hostId ] ;
260
+ const remaining = 74 - currentProgress ;
261
+ this . setHostProgress ( hostId ,
262
+ currentProgress + Math . floor ( remaining / 10 )
263
+ ) ;
264
+ } , 100 ) ;
265
+
266
+ try {
267
+ await this . props . activateInterceptor ( {
268
+ action : 'setup' ,
269
+ hostId
270
+ } ) ;
271
+
272
+ this . setHostProgress ( hostId , 75 ) ;
273
+ await this . launchInterceptor ( hostId ) ;
274
+ } finally {
275
+ clearInterval ( interval ) ;
276
+ this . setHostProgress ( hostId , undefined ) ;
277
+ }
278
+ }
279
+
280
+ async launchInterceptor ( hostId : string ) {
281
+ // Logarithmically move towards 100% while setup runs:
282
+ let interval = setInterval ( ( ) => {
283
+ const currentProgress = this . hostProgress [ hostId ] ;
284
+ const remaining = 99 - currentProgress ;
285
+ this . setHostProgress ( hostId ,
286
+ currentProgress + Math . floor ( remaining / 5 )
287
+ ) ;
288
+ } , 100 ) ;
289
+
290
+ try {
291
+ await this . props . activateInterceptor ( {
292
+ action : 'launch' ,
293
+ hostId
294
+ } ) ;
295
+
296
+ this . setHostProgress ( hostId , 100 ) ;
297
+ await delay ( 10 ) ; // Tiny delay purely for nice UI purposes
298
+ this . viewHostTargets ( hostId ) ;
299
+ } finally {
300
+ clearInterval ( interval ) ;
301
+ this . setHostProgress ( hostId , undefined ) ;
302
+ }
303
+ }
304
+
245
305
@action . bound
246
306
interceptTarget ( targetId : string ) {
247
307
const host = this . selectedHost ;
@@ -317,28 +377,24 @@ class FridaConfig extends React.Component<{
317
377
spinnerText = { `Waiting for ${ this . deviceClassName } devices to attach to...` }
318
378
targets = { this . fridaHosts . map ( host => {
319
379
const { id, name, state } = host ;
320
- const activating = this . inProgressHostIds . includes ( id ) ;
380
+ const activating = this . hostProgress [ id ] !== undefined ;
321
381
322
382
return {
323
383
id,
324
384
title : `${ this . deviceClassName } device ${ name } in state ${ state } ` ,
385
+ icon : id . includes ( "emulator-" )
386
+ ? < Icon icon = { [ 'far' , 'window-maximize' ] } />
387
+ : id . match ( / \d + \. \d + \. \d + \. \d + : \d + / )
388
+ ? < Icon icon = { [ 'fas' , 'network-wired' ] } />
389
+ : < Icon icon = { [ 'fas' , 'mobile-alt' ] } /> ,
325
390
status : activating
326
391
? 'activating'
327
392
: state === 'unavailable'
328
393
? 'unavailable'
329
394
// Available here means clickable - interceptable/setupable/launchable
330
395
: 'available' ,
331
- content : < p >
332
- {
333
- activating
334
- ? < Icon icon = { [ 'fas' , 'spinner' ] } spin />
335
- : id . includes ( "emulator-" )
336
- ? < Icon icon = { [ 'far' , 'window-maximize' ] } />
337
- : id . match ( / \d + \. \d + \. \d + \. \d + : \d + / )
338
- ? < Icon icon = { [ 'fas' , 'network-wired' ] } />
339
- : < Icon icon = { [ 'fas' , 'mobile-alt' ] } />
340
- } { name } < br /> { state }
341
- </ p >
396
+ progress : this . hostProgress [ id ] ,
397
+ content : < p > { name } < br /> { state } </ p >
342
398
} ;
343
399
} ) }
344
400
interceptTarget = { this . selectHost }
0 commit comments