import { useState , useEffect , useRef , Dispatch , SetStateAction } from 'react' ; import TdpClient , { ImageFragment } from 'teleport/lib/tdp/client' ; import { TopBarHeight } from './TopBar' ; import cfg from 'teleport/config' ; import { getAccessToken , getHostName } from 'teleport/services/api' ; import { ButtonState , ScrollAxis } from 'teleport/lib/tdp/codec' ; import { Attempt } from 'shared/hooks/useAttemptNext' ; export default function useTdpClientCanvas ( props ) { const { username , desktopName , clusterId , setTdpConnection , setWsConnection , } = props ; const [ tdpClient , setTdpClient ] = useState < TdpClient | null > ( null ) ; const firstImageFragmentRef = useRef ( true ) ; useEffect ( ( ) => { const { width , height } = getDisplaySize ( ) ; const addr = cfg . api . desktopWsAddr . replace ( ':fqdm' , getHostName ( ) ) . replace ( ':clusterId' , clusterId ) . replace ( ':desktopName' , desktopName ) . replace ( ':token' , getAccessToken ( ) ) . replace ( ':username' , username ) . replace ( ':width' , width . toString ( ) ) . replace ( ':height' , height . toString ( ) ) ; setTdpClient ( new TdpClient ( addr , username ) ) ; } , [ clusterId , username , desktopName ] ) ; const syncCanvasSizeToDisplaySize = ( canvas ) => { const { width , height } = getDisplaySize ( ) ; canvas . width = width ; canvas . height = height ; } ; const onImageFragment = ( ctx , data ) => { if ( firstImageFragmentRef . current ) { syncCanvasSizeToDisplaySize ( ctx . canvas ) ; setTdpConnection ( { status : 'success' } ) ; firstImageFragmentRef . current = false ; } ctx . drawImage ( data . image , data . left , data . top ) ; } ; const onTdpError = ( err ) => { setTdpConnection ( { status : 'failed' , statusText : err . message } ) ; } ; const onWsClose = ( ) => { setWsConnection ( 'closed' ) ; } ; const onWsOpen = ( ) => { setWsConnection ( 'open' ) ; } ; const onKeyDown = ( cli , e ) => { cli . sendKeyboardInput ( e . code , ButtonState . DOWN ) ; } ; const onKeyUp = ( cli , e ) => { cli . sendKeyboardInput ( e . code , ButtonState . UP ) ; } ; const onMouseMove = ( cli , canvas , e ) => { const rect = canvas . getBoundingClientRect ( ) ; const x = e . clientX - rect . left ; const y = e . clientY - rect . top ; cli . sendMouseMove ( x , y ) ; } ; const onMouseDown = ( cli , e ) => { if ( e . button === 0 || e . button === 1 || e . button === 2 ) { cli . sendMouseButton ( e . button , ButtonState . DOWN ) ; } } ; const onMouseUp = ( cli , e ) => { if ( e . button === 0 || e . button === 1 || e . button === 2 ) { cli . sendMouseButton ( e . button , ButtonState . UP ) ; } } ; const onMouseWheelScroll = ( cli , e ) => { if ( e . deltaMode === WheelEvent . DOM_DELTA_PIXEL ) { if ( e . deltaX ) { cli . sendMouseWheelScroll ( ScrollAxis . HORIZONTAL , - e . deltaX ) ; } if ( e . deltaY ) { cli . sendMouseWheelScroll ( ScrollAxis . VERTICAL , - e . deltaY ) ; } } } ; return { tdpClient , onImageFragment , onTdpError , onWsClose , onWsOpen , onKeyDown , onKeyUp , onMouseMove , onMouseDown , onMouseUp , onMouseWheelScroll , } ; } function getDisplaySize ( ) { return { width : window . innerWidth , height : window . innerHeight - TopBarHeight , } ; } type Props = { username : string ; desktopName : string ; clusterId : string ; setTdpConnection : Dispatch < SetStateAction < Attempt > > ; setWsConnection : Dispatch < SetStateAction < 'open' | 'closed' > > ; } ;