@@ -4,7 +4,9 @@ import { computed, observable, action, autorun, flow, runInAction } from 'mobx';
44import { observer , inject , disposeOnUnmount } from 'mobx-react' ;
55
66import { delay } from '../../../util/promise' ;
7+ import { UnreachableCheck } from '../../../util/error' ;
78import { styled } from '../../../styles' ;
9+ import { Icon } from '../../../icons' ;
810
911import { Interceptor } from '../../../model/interception/interceptors' ;
1012import { ProxyStore } from '../../../model/proxy-store' ;
@@ -16,7 +18,6 @@ import { FridaActivationOptions, FridaHost, FridaTarget } from '../../../model/i
1618import { getDetailedInterceptorMetadata } from '../../../services/server-api' ;
1719
1820import { TextInput } from '../../common/inputs' ;
19- import { Icon } from '../../../icons' ;
2021import { InterceptionTargetList } from './intercept-target-list' ;
2122import { IconButton } from '../../common/icon-button' ;
2223
@@ -116,6 +117,45 @@ const SearchBox = styled(TextInput)`
116117 }
117118` ;
118119
120+ const HostName = styled . p `
121+ font-weight: bold;
122+ ` ;
123+
124+ const getStateDescriptionText = ( { type, state } : {
125+ type : FridaHost [ 'type' ] ,
126+ state : Exclude < FridaHost [ 'state' ] , 'available' >
127+ } ) => {
128+ if ( state === 'launch-required' ) return 'Frida launch required' ;
129+ else if ( state === 'setup-required' ) return 'Frida installation required' ;
130+ else if ( state === 'unavailable' ) {
131+ if ( type === 'android' ) {
132+ return 'Root access not available' ;
133+ } else {
134+ return 'Device must be jailbroken and running Frida server' ;
135+ }
136+ }
137+
138+ throw new UnreachableCheck ( state ) ;
139+ } ;
140+
141+ const StateDescription = styled ( ( { type, state, className } : {
142+ type : FridaHost [ 'type' ] ,
143+ state : FridaHost [ 'state' ] ,
144+ className ?: string
145+ } ) => {
146+ if ( state === 'available' ) return null ;
147+
148+ return < p className = { className } >
149+ { getStateDescriptionText ( { type, state } ) }
150+ </ p > ;
151+ } ) `
152+ margin-top: 5px;
153+ font-style: italic;
154+
155+ white-space: normal;
156+ text-wrap: balance;
157+ ` ;
158+
119159// We actively hide specific known non-interceptable apps:
120160const INCOMPATIBLE_APP_IDS : string [ ] = [
121161 "com.apple.mobilesafari" ,
@@ -402,7 +442,7 @@ class FridaConfig extends React.Component<{
402442
403443 return {
404444 id,
405- title : `${ this . deviceClassName } device ${ name } (${ id } ) in state ${ state } ` ,
445+ title : `${ this . deviceClassName } device ${ name } (${ id } ): ${ _ . startCase ( state ) } ` ,
406446 icon : id . includes ( "emulator-" )
407447 ? < Icon icon = { [ 'far' , 'window-maximize' ] } />
408448 : id . match ( / \d + \. \d + \. \d + \. \d + : \d + / )
@@ -415,7 +455,10 @@ class FridaConfig extends React.Component<{
415455 // Available here means clickable - interceptable/setupable/launchable
416456 : 'available' ,
417457 progress : this . hostProgress [ id ] ,
418- content : < p > { name } < br /> { state } </ p >
458+ content : < div >
459+ < HostName > { name } </ HostName >
460+ < StateDescription type = { host . type } state = { host . state } />
461+ </ div >
419462 } ;
420463 } ) }
421464 interceptTarget = { this . selectHost }
0 commit comments