main
parent
10074264c7
commit
47b3d3e9c3
1 changed files with 109 additions and 0 deletions
@ -0,0 +1,109 @@ |
|||||||
|
import { useEffect, useRef, useState } from 'react'; |
||||||
|
import { RFB } from 'novnc-node'; |
||||||
|
|
||||||
|
type VncProps = { |
||||||
|
// The URL for the VNC connection: protocol, host, port, and path.
|
||||||
|
url: string; |
||||||
|
|
||||||
|
// Define width and height via style or separate props
|
||||||
|
style?: { width: number | string; height: number | string }; |
||||||
|
width?: number | string; |
||||||
|
height?: number | string; |
||||||
|
|
||||||
|
// Force a URL to be communicated with as encrypted.
|
||||||
|
encrypt?: boolean; |
||||||
|
|
||||||
|
// List of WebSocket protocols this connection should support.
|
||||||
|
wsProtocols?: string[]; |
||||||
|
|
||||||
|
// VNC connection changes.
|
||||||
|
onUpdateState?: () => void; |
||||||
|
|
||||||
|
onPasswordRequired?: () => void; |
||||||
|
|
||||||
|
// Alert is raised on the VNC connection.
|
||||||
|
onBell?: () => void; |
||||||
|
|
||||||
|
// The desktop name is entered for the connection.
|
||||||
|
onDesktopName?: () => void; |
||||||
|
|
||||||
|
connectTimeout?: number; |
||||||
|
|
||||||
|
disconnectTimeout?: number; |
||||||
|
|
||||||
|
// A VNC connection should disconnect other connections before connecting.
|
||||||
|
shared?: boolean; |
||||||
|
|
||||||
|
trueColor?: boolean; |
||||||
|
localCursor?: boolean; |
||||||
|
}; |
||||||
|
|
||||||
|
const VncDisplay = (props: VncProps): JSX.Element => { |
||||||
|
const canvasRef = useRef<HTMLCanvasElement>(null); |
||||||
|
const [rfb, setRfb] = useState<typeof RFB>(undefined); |
||||||
|
const { style, url, encrypt, ...opts } = props; |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
if (!rfb) |
||||||
|
setRfb( |
||||||
|
new RFB({ |
||||||
|
...opts, |
||||||
|
encrypt: encrypt !== null ? encrypt : url.startsWith('wss:'), |
||||||
|
target: canvasRef.current, |
||||||
|
}), |
||||||
|
); |
||||||
|
|
||||||
|
if (!rfb) return; |
||||||
|
|
||||||
|
if (!canvasRef.current) { |
||||||
|
/* eslint-disable consistent-return */ |
||||||
|
return (): void => rfb.disconnect(); |
||||||
|
} |
||||||
|
|
||||||
|
rfb.connect(url); |
||||||
|
|
||||||
|
return (): void => rfb.disconnect(); |
||||||
|
}, [rfb, encrypt, opts, url]); |
||||||
|
|
||||||
|
const handleMouseEnter = () => { |
||||||
|
if (!rfb) return; |
||||||
|
// document.activeElement && document.activeElement.blur();
|
||||||
|
rfb.get_keyboard().grab(); |
||||||
|
rfb.get_mouse().grab(); |
||||||
|
}; |
||||||
|
|
||||||
|
const handleMouseLeave = () => { |
||||||
|
if (!rfb) return; |
||||||
|
|
||||||
|
rfb.get_keyboard().ungrab(); |
||||||
|
rfb.get_mouse().ungrab(); |
||||||
|
}; |
||||||
|
|
||||||
|
return ( |
||||||
|
<canvas |
||||||
|
style={style} |
||||||
|
ref={canvasRef} |
||||||
|
onMouseEnter={handleMouseEnter} |
||||||
|
onMouseLeave={handleMouseLeave} |
||||||
|
/> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
VncDisplay.defaultProps = { |
||||||
|
style: null, |
||||||
|
encrypt: null, |
||||||
|
wsProtocols: ['binary'], |
||||||
|
trueColor: true, |
||||||
|
localCursor: true, |
||||||
|
connectTimeout: 5, |
||||||
|
disconnectTimeout: 5, |
||||||
|
width: 1280, |
||||||
|
height: 720, |
||||||
|
onUpdateState: null, |
||||||
|
onPasswordRequired: null, |
||||||
|
onBell: null, |
||||||
|
onDesktopName: null, |
||||||
|
shared: false, |
||||||
|
}; |
||||||
|
|
||||||
|
export default VncDisplay; |
Loading…
Reference in new issue