import RFB from '@novnc/novnc/core/rfb'; import Websock from '@novnc/novnc/core/websock'; import { useEffect } from 'react'; const rfbConnect: RfbConnectFunction = ({ background = '', clipViewport = false, compressionLevel = 2, dragViewport = false, focusOnClick = false, onConnect, onDisconnect, onWsClose, onWsError, qualityLevel = 6, resizeSession = true, rfb, rfbScreen, scaleViewport = true, showDotCursor = false, url, viewOnly = false, }) => { if (!rfbScreen?.current || rfb?.current) return; rfbScreen.current.innerHTML = ''; rfb.current = new RFB(rfbScreen.current, url); rfb.current.background = background; rfb.current.clipViewport = clipViewport; rfb.current.compressionLevel = compressionLevel; rfb.current.dragViewport = dragViewport; rfb.current.focusOnClick = focusOnClick; rfb.current.qualityLevel = qualityLevel; rfb.current.resizeSession = resizeSession; rfb.current.scaleViewport = scaleViewport; rfb.current.showDotCursor = showDotCursor; rfb.current.viewOnly = viewOnly; // RFB extends custom class EventTargetMixin; // the usual .on or .once doesn't exist. if (onConnect) { rfb.current.addEventListener('connect', onConnect); } if (onDisconnect) { rfb.current.addEventListener('disconnect', onDisconnect); } /* eslint-disable no-underscore-dangle */ const ws: typeof Websock = rfb.current._sock; const socketClose = ws._eventHandlers.close; const socketError = ws._eventHandlers.error; ws.on('close', (e?: WebsockCloseEvent) => { socketClose(e); onWsClose?.call(null, e); }); ws.on('error', (e: Event) => { socketError(e); onWsError?.call(null, e); }); /* eslint-enable no-underscore-dangle */ }; const rfbDisconnect: RfbDisconnectFunction = (rfb) => { if (!rfb?.current) return; rfb.current.disconnect(); rfb.current = null; }; const VncDisplay = (props: VncDisplayProps): JSX.Element => { const { onConnect, onDisconnect, onWsClose, onWsError, rfb, rfbConnectArgs, rfbScreen, url: initUrl, } = props; useEffect(() => { if (rfbConnectArgs) { const { url = initUrl } = rfbConnectArgs; if (!url) return; const args: RfbConnectArgs = { onConnect, onDisconnect, onWsClose, onWsError, rfb, rfbScreen, url, ...rfbConnectArgs, }; rfbConnect(args); } else { rfbDisconnect(rfb); } }, [ initUrl, onConnect, onDisconnect, onWsClose, onWsError, rfb, rfbConnectArgs, rfbScreen, ]); useEffect( () => () => { rfbDisconnect(rfb); }, [rfb], ); const handleMouseEnter = () => { if ( document.activeElement && document.activeElement instanceof HTMLElement ) { document.activeElement.blur(); } if (rfb?.current) rfb.current.focus(); }; return (
); }; VncDisplay.displayName = 'VncDisplay'; export default VncDisplay;