11/* eslint-disable react/jsx-props-no-spreading */
22import { useResizable } from 'react-resizable-layout' ;
33import React , { useCallback , useState } from 'react' ;
4- import { INode , ITreeViewOnSelectProps } from 'react-accessible-treeview' ;
4+ import {
5+ flattenTree ,
6+ INode ,
7+ ITreeViewOnSelectProps ,
8+ } from 'react-accessible-treeview' ;
59import { Navbar } from 'react-daisyui' ;
610import {
711 DevicePhoneMobileIcon ,
@@ -29,7 +33,7 @@ function MainView(): React.JSX.Element {
2933 const [ deviceExpanded , setDeviceExpanded ] = useState ( false ) ;
3034 const [ searchExpanded , setSearchExpanded ] = useState ( false ) ;
3135 const [ logMessages , setLogMessages ] = useState <
32- { time : string ; type : string ; message : string , id :number } [ ]
36+ { time : string ; type : string ; message : string ; id : number } [ ]
3337 > ( [ ] ) ;
3438 const [ selectedCoord , setSelectedCoord ] = useState ( {
3539 x : 0 ,
@@ -81,7 +85,7 @@ function MainView(): React.JSX.Element {
8185 }
8286 } ;
8387
84- const viewHovered = ( element : INode ) => {
88+ const viewHovered = useCallback ( ( element : INode ) => {
8589 setHoveredCoord ( {
8690 x : element . metadata ! . x1 ! as number ,
8791 y : element . metadata ! . y1 ! as number ,
@@ -90,7 +94,7 @@ function MainView(): React.JSX.Element {
9094 height :
9195 ( element . metadata ! . y2 ! as number ) - ( element . metadata ! . y1 ! as number ) ,
9296 } ) ;
93- } ;
97+ } , [ ] ) ;
9498
9599 const onHoveredViewSelected = ( view : INode ) => {
96100 if ( view ) {
@@ -102,44 +106,89 @@ function MainView(): React.JSX.Element {
102106 setSelectedDevice ( null ) ;
103107 } ;
104108
105- const messageReceived = useCallback (
106- ( data : any ) => {
107- if ( ! data . announcement ) {
108- setSelectedView ( 0 ) ;
109- setViewHierarchy ( data ) ;
110- setSearchTerm ( '' ) ;
111- } else if ( data . announcement ) {
112- toast . info (
113- < div className = "flex flex-col" >
114- < h2 className = "text-md" > accessibility announcement </ h2 >
115- < div className = "text-sm" > { data . announcement } </ div >
116- </ div > ,
117- ) ;
118- const currentDate = new Date ( ) ;
119- const day = currentDate . getDay ( ) ;
120- const month = currentDate . getMonth ( ) ;
121- const year = currentDate . getFullYear ( ) ;
122- const hour = currentDate . getHours ( ) ;
123- const minutes = currentDate . getMinutes ( ) ;
124- const seconds = currentDate . getSeconds ( ) ;
125- const message = {
126- time : `${ month } /${ day } /${ year } -${ hour } :${ minutes } :${ seconds } ` ,
127- message : data . announcement ,
128- type : 'accessibility announcement' ,
129- id : Math . random ( ) * ( 5000 - 0 ) + 0 ,
130- } ;
109+ const findOverlappingViews = ( data ) => {
110+ const flatTree = flattenTree ( data ) ;
111+ const centers : any = [ ] ;
112+ const overlaps : any = [ ] ;
113+ flatTree . filter ( ( item ) => {
114+ const clickable =
115+ item . metadata &&
116+ item . metadata . properties &&
117+ item . metadata . properties . includes ( 'clickable' ) ;
118+ if ( clickable ) {
119+ const scaleFactor = item . metadata . dpScaleFactor ;
120+ centers . push ( {
121+ element : item ,
122+ center : {
123+ top : ( ( item . metadata . y2 + item . metadata . y1 ) * scaleFactor ) / 2 ,
124+ left : ( ( item . metadata . x2 + item . metadata . x1 ) * scaleFactor ) / 2 ,
125+ } ,
126+ } ) ;
127+ }
128+ return clickable ;
129+ } ) ;
130+ centers . forEach ( ( item1 , index ) => {
131+ centers . slice ( index + 1 ) . forEach ( item2 => {
132+ if ( Math . sqrt ( Math . pow ( item2 . center . left - item1 . center . left , 2 ) + Math . pow ( item2 . center . top - item1 . center . top , 2 ) ) < 24 ) {
133+ overlaps . push ( item1 . element ) ;
134+ overlaps . push ( item2 . element ) ;
135+ }
136+ } ) ;
137+ } ) ;
138+ console . log ( 'possible overlaps' , overlaps ) ;
139+ } ;
140+
141+ const messageReceived = useCallback ( ( data : any ) => {
142+ if ( ! data . announcement ) {
143+ setSelectedView ( 0 ) ;
144+ setViewHierarchy ( data ) ;
145+ findOverlappingViews ( data ) ;
146+ setSearchTerm ( '' ) ;
147+ } else if ( data . announcement ) {
148+ toast . info (
149+ < div className = "flex flex-col" >
150+ < h2 className = "text-md" > accessibility announcement </ h2 >
151+ < div className = "text-sm" > { data . announcement } </ div >
152+ </ div > ,
153+ ) ;
154+ const currentDate = new Date ( ) ;
155+ const day = currentDate . getDay ( ) ;
156+ const month = currentDate . getMonth ( ) ;
157+ const year = currentDate . getFullYear ( ) ;
158+ const hour = currentDate . getHours ( ) ;
159+ const minutes = currentDate . getMinutes ( ) ;
160+ const seconds = currentDate . getSeconds ( ) ;
161+ const message = {
162+ time : `${ month } /${ day } /${ year } -${ hour } :${ minutes } :${ seconds } ` ,
163+ message : data . announcement ,
164+ type : 'accessibility announcement' ,
165+ id : Math . random ( ) * ( 5000 - 0 ) + 0 ,
166+ } ;
167+
168+ setLogMessages ( ( logMessages ) => [ ...logMessages , message ] ) ;
169+ }
170+ } , [ ] ) ;
171+
172+ const handleBlur = useCallback ( ( e : { currentTarget : any } ) => {
173+ const { currentTarget } = e ;
131174
132- setLogMessages ( logMessages => [
133- ...logMessages ,
134- message ,
135- ] ) ;
175+ // Give browser time to focus the next element
176+ requestAnimationFrame ( ( ) => {
177+ // Check if the new focused element is a child of the original container
178+ if ( ! currentTarget . contains ( document . activeElement ) ) {
179+ ( currentTarget as HTMLDetailsElement ) . open = false ;
136180 }
137- } ,
138- [ ] ,
139- ) ;
181+ } ) ;
182+ } , [ ] ) ;
140183
141184 const deviceSelected = ( device : IDevice ) => {
142185 setSelectedDevice ( device ) ;
186+ toast . info (
187+ < div className = "flex flex-col" >
188+ < h2 className = "text-md" > device connected</ h2 >
189+ < div className = "text-sm" > { device . model } </ div >
190+ </ div > ,
191+ ) ;
143192 } ;
144193
145194 const performSearch = ( term : string ) => {
@@ -191,6 +240,7 @@ function MainView(): React.JSX.Element {
191240 onToggle = { ( e ) =>
192241 setSearchExpanded ( ( e . currentTarget as HTMLDetailsElement ) . open )
193242 }
243+ onBlur = { handleBlur }
194244 >
195245 < summary
196246 className = { `text-xl font-medium btn ${ searchExpanded && 'btn-active' } btn-ghost` }
@@ -203,10 +253,10 @@ function MainView(): React.JSX.Element {
203253 < ul
204254 className = "p-2 shadow dropdown-content menu bg-base-100 rounded-box right-0 w-[500px] z-10"
205255 role = "presentation"
256+ tabIndex = { - 1 }
206257 >
207258 < SearchView performSearch = { performSearch } />
208259 </ ul >
209-
210260 </ details >
211261
212262 < details
@@ -215,6 +265,7 @@ function MainView(): React.JSX.Element {
215265 onToggle = { ( e ) =>
216266 setDeviceExpanded ( ( e . currentTarget as HTMLDetailsElement ) . open )
217267 }
268+ onBlur = { handleBlur }
218269 >
219270 < summary
220271 className = { `text-xl font-medium btn ${ deviceExpanded && 'btn-active' } btn-ghost` }
@@ -237,6 +288,7 @@ function MainView(): React.JSX.Element {
237288 < ul
238289 className = "p-2 shadow dropdown-content menu bg-base-100 rounded-box right-0 w-[500px] z-10"
239290 role = "presentation"
291+ tabIndex = { - 1 }
240292 >
241293 < ConnectDevice onDeviceConnected = { deviceSelected } />
242294 </ ul >
@@ -246,7 +298,11 @@ function MainView(): React.JSX.Element {
246298 </ Navbar . End >
247299 </ Navbar >
248300
249- < div className = "overflow-hidden flex grow max-w-[calc(100vw-1rem)]" role = "region" aria-label = "Screenshot" >
301+ < div
302+ className = "overflow-hidden flex grow max-w-[calc(100vw-1rem)]"
303+ role = "region"
304+ aria-label = "Screenshot"
305+ >
250306 < div
251307 className = { `shrink-0 contents pt-4 ${ isTreeDragging ? 'dragging' : '' } ` }
252308 style = { { width : treeW , maxWidth : treeW } }
@@ -265,7 +321,11 @@ function MainView(): React.JSX.Element {
265321 label = "Resize between screenshot and view hierarchy"
266322 />
267323 < div className = "flex grow" >
268- < div className = "overflow-x-auto overflow-y-auto grow" role = "region" aria-label = "View Heirarchy" >
324+ < div
325+ className = "overflow-x-auto overflow-y-auto grow"
326+ role = "region"
327+ aria-label = "View Heirarchy"
328+ >
269329 < BasicTreeView
270330 tree = { viewHierarchy }
271331 onViewSelected = { viewSelected }
@@ -299,6 +359,7 @@ function MainView(): React.JSX.Element {
299359 hideProgressBar
300360 newestOnTop
301361 closeOnClick = { false }
362+ closeButton = { false }
302363 rtl = { false }
303364 pauseOnFocusLoss
304365 draggable
0 commit comments