@@ -1059,7 +1059,7 @@ var JSONResponse = {
10591059 var format = target . format ;
10601060 if ( typeof format == 'string' && FORMAT_PRIORITIES [ format ] != null ) {
10611061 var verifier = max . code < JSONResponse . COMPARE_FORMAT_CHANGE && StringUtil . isNotEmpty ( format , true )
1062- ? FORMAT_VERIFIERS [ format ] : null ;
1062+ && StringUtil . isNotEmpty ( real , true ) ? FORMAT_VERIFIERS [ format ] : null ;
10631063 if ( typeof verifier == 'function' && verifier ( real ) != true ) {
10641064 max . code = JSONResponse . COMPARE_FORMAT_CHANGE - ( guess != true ? 0 : 1 ) ;
10651065 max . msg = '不是 ' + format + " 格式!" ;
@@ -1664,11 +1664,15 @@ var JSONResponse = {
16641664
16651665 /**根据 APIJSON 引用赋值路径精准地获取值
16661666 */
1667- getValByPath : function ( target , pathKeys , isTry ) {
1667+ getValByPath : function ( target , pathKeys , isTry , isDesc ) {
16681668 if ( target == null ) {
16691669 return null ;
16701670 }
16711671
1672+ if ( StringUtil . isString ( pathKeys ) ) {
1673+ pathKeys = StringUtil . split ( pathKeys , '/' , false )
1674+ }
1675+
16721676 var tgt = target ;
16731677 var depth = pathKeys == null ? 0 : pathKeys . length
16741678 if ( depth <= 0 ) {
@@ -1689,14 +1693,44 @@ var JSONResponse = {
16891693 if ( tgt instanceof Object ) {
16901694 if ( k == '' ) {
16911695 if ( tgt instanceof Array ) {
1692- k = 0 ;
1696+ for ( var j = 0 ; j < tgt . length ; j ++ ) {
1697+ var ind = isDesc ? tgt . length - 1 - j : j ;
1698+ var val = tgt [ ind ]
1699+ if ( i >= depth - 1 ) {
1700+ if ( val == null ) {
1701+ continue
1702+ }
1703+ return val
1704+ }
1705+
1706+ var ks = pathKeys . slice ( i + 1 ) ;
1707+ var child = JSONResponse . getValByPath ( val , ks , isTry , isDesc ) ;
1708+ if ( child != null ) {
1709+ return child
1710+ }
1711+ }
16931712 } else {
1694- ks = Object . keys ( tgt ) ;
1695- k = ks == null ? null : ks [ 0 ] ;
1696- if ( k == null ) {
1697- return null ;
1713+ var tks = Object . keys ( tgt ) ;
1714+ for ( var j = 0 ; j < tks . length ; j ++ ) {
1715+ var ind = isDesc ? tks . length - 1 - j : j ;
1716+ var k2 = tks [ ind ]
1717+ var val = tgt [ k2 ]
1718+ if ( i >= depth - 1 ) {
1719+ if ( val == null ) {
1720+ continue
1721+ }
1722+ return val
1723+ }
1724+
1725+ var ks = pathKeys . slice ( i + 1 ) ;
1726+ var child = JSONResponse . getValByPath ( val , ks , isTry , isDesc ) ;
1727+ if ( child != null ) {
1728+ return child
1729+ }
16981730 }
16991731 }
1732+
1733+ return null ;
17001734 }
17011735 else {
17021736 k = decodeURI ( k )
@@ -2584,8 +2618,8 @@ var JSONResponse = {
25842618 } ,
25852619
25862620 drawDetections : function ( canvas , detection , options , img , ctx , isClear ) {
2587- if ( Object . keys ( JSONResponse . isObject ( detection ) ? detection : { } ) <= 0 ) {
2588- console . error ( 'drawDetections: invalid detection input' ) ;
2621+ if ( StringUtil . isEmpty ( JSONResponse . isObject ( detection ) ? detection : null ) ) {
2622+ console . log ( 'drawDetections: invalid detection input: ' + StringUtil . trim ( detection ) ) ;
25892623 return ;
25902624 }
25912625
@@ -2677,7 +2711,10 @@ var JSONResponse = {
26772711 }
26782712
26792713 // Label
2680- const label = mark + ( isDiff ? ( isBefore ? '- ' : '+ ' ) : '' ) + `${ item . ocr || item . label || '' } ${ item . id == null ? '' : '-' + item . id } ${ ( ( JSONResponse . getScore ( item ) || 0 ) * 100 ) . toFixed ( 0 ) } %${ angle == 0 ? '' : ' ' + Math . round ( angle ) + '°' } ` ;
2714+ const id = item . viewIdName || item . id
2715+ const viewPath = isHovered ? item . viewPath : null
2716+ const gravity = item . gravity
2717+ const label = mark + ( isDiff ? ( isBefore ? '- ' : '+ ' ) : '' ) + ( StringUtil . isEmpty ( viewPath ) ? `${ id == null ? '' : id } ` : StringUtil . limitLength ( viewPath , 30 , 'start' ) ) ;
26812718 // ctx.font = 'bold 36px';
26822719 // const size = ctx.measureText(label);
26832720 // const textHeight = size.height || height*0.1; // Math.max(height*0.1, size.height);
@@ -2842,6 +2879,141 @@ var JSONResponse = {
28422879 }
28432880 } ) ;
28442881 }
2882+ } ,
2883+
2884+ INTEREST_TYPES : [
2885+ "TextView" ,
2886+ "ImageView" ,
2887+ "Button" ,
2888+ "EditText" ,
2889+ "CheckBox" ,
2890+ "Switch" ,
2891+ "ImageButton"
2892+ ] ,
2893+
2894+ getPx : function ( v ) {
2895+ if ( ! v ) return 0 ;
2896+ if ( typeof v === "number" ) return v ;
2897+ return ( v . real || v . px ) ?? 0 ;
2898+ } ,
2899+
2900+ isInteresting : function ( type ) {
2901+ if ( ! type ) return false ;
2902+ return JSONResponse . INTEREST_TYPES . some ( t => type . includes ( t ) ) ;
2903+ } ,
2904+
2905+ computeOffset : function ( input ) {
2906+ let offsetX = 0 ;
2907+ let offsetY = 0 ;
2908+
2909+ if ( input . popupWindow ) {
2910+ offsetX = input . popupWindowX ?? 0 ;
2911+ offsetY = input . popupWindowY ?? 0 ;
2912+ }
2913+ else if ( input . dialog ) {
2914+ offsetX = input . dialogX ?? 0 ;
2915+ offsetY = input . dialogY ?? 0 ;
2916+ }
2917+ else if ( input . fragment ) {
2918+ offsetX = input . fragmentX ?? 0 ;
2919+ offsetY = input . fragmentY ?? 0 ;
2920+ }
2921+ else {
2922+ offsetX = input . contentX ?? 0 ;
2923+ offsetY = input . contentY ?? 0 ;
2924+ }
2925+
2926+ return { offsetX, offsetY } ;
2927+ } ,
2928+
2929+ convertViewTree : function ( root , input ) {
2930+ input = input || { } ;
2931+
2932+ const results = [ ] ;
2933+ let id = 1 ;
2934+ const offset = JSONResponse . computeOffset ( input ) ;
2935+
2936+ function walk ( node , parentX = 0 , parentY = 0 , path = "" , assertPath = '' ) {
2937+ if ( ! node ) {
2938+ return ;
2939+ }
2940+
2941+ const x = parentX + JSONResponse . getPx ( node . x ) ;
2942+ const y = parentY + JSONResponse . getPx ( node . y ) ;
2943+ let w = JSONResponse . getPx ( node . width ) ;
2944+ let h = JSONResponse . getPx ( node . height ) ;
2945+ if ( w <= 0 || h <= 0 ) {
2946+ w = 0 ;
2947+ h = 0 ;
2948+ }
2949+
2950+ var viewType = node . type || ''
2951+ var viewIdName = node . viewIdName || ''
2952+ if ( StringUtil . isString ( viewType ) ) {
2953+ if ( viewType . startsWith ( 'android.widget.' ) ) {
2954+ viewType = viewType . substring ( 'android.widget.' . length )
2955+ } else if ( viewType . startsWith ( 'android.view.' ) ) {
2956+ viewType = viewType . substring ( 'android.view.' . length )
2957+ } else if ( viewType . startsWith ( 'androidx.widget.' ) ) {
2958+ viewType = viewType . substring ( 'androidx.widget.' . length )
2959+ } else if ( viewType . startsWith ( 'androidx.view.' ) ) {
2960+ viewType = viewType . substring ( 'androidx.view.' . length )
2961+ }
2962+ }
2963+
2964+ if ( w > 0 && h > 0 && JSONResponse . isInteresting ( viewType ) ) {
2965+ const screenX = x + offset . offsetX ;
2966+ const screenY = y + offset . offsetY ;
2967+ results . push ( {
2968+ id : id ++ ,
2969+ bbox : [ screenX , screenY , w , h ] ,
2970+ label : viewType ,
2971+ text : node . text ?? null ,
2972+ viewId : node . viewId ?? null ,
2973+ viewIdName : viewIdName ?? null ,
2974+ viewPath : ( StringUtil . isEmpty ( path ) ? '' : path + "/" ) + ( viewIdName || viewType ) ,
2975+ assertPath : ( StringUtil . isEmpty ( assertPath ) ? '' : assertPath + "/" ) + ( viewType + ( StringUtil . isEmpty ( viewIdName ) ? '' : ':' + viewIdName ) ) ,
2976+ center : [ screenX + w / 2 , screenY + h / 2 ] ,
2977+ area : w * h
2978+ } ) ;
2979+ }
2980+
2981+ var arr = node . childList || [ ]
2982+ if ( ! Array . isArray ( arr ) ) {
2983+ return ;
2984+ }
2985+
2986+ for ( let i = 0 ; i < arr . length ; i ++ ) {
2987+ const child = arr [ i ] ;
2988+ const childPath = ( StringUtil . isEmpty ( path ) ? '' : path + "/" ) + ( viewIdName || viewType ) + "/" + i ;
2989+ const childAssertPath = ( StringUtil . isEmpty ( assertPath ) ? '' : assertPath + "/" ) + ( viewType + ( StringUtil . isEmpty ( viewIdName ) ? '' : ':' + viewIdName ) ) + "/" + i ;
2990+ walk ( child , x , y , childPath , childAssertPath ) ;
2991+ }
2992+ }
2993+
2994+ walk ( root , 0 , 0 , "" ) ;
2995+
2996+ return results ;
2997+ } ,
2998+
2999+ getNodeByPath : function ( root , path ) {
3000+ if ( root == null || StringUtil . isEmpty ( path ) ) {
3001+ return root ;
3002+ }
3003+
3004+ const parts = path . split ( "/" ) ;
3005+ let node = root ;
3006+
3007+ for ( let i = 0 ; i < parts . length ; i += 2 ) {
3008+ const key = parts [ i ] ;
3009+ const index = Number ( parts [ i + 1 ] ) ;
3010+ node = node ?. [ key ] ?. [ index ] ;
3011+ if ( node == null ) {
3012+ return null ;
3013+ }
3014+ }
3015+
3016+ return node ;
28453017 }
28463018
28473019} ;
0 commit comments