diff --git a/README.md b/README.md index e7ca982..889a455 100644 --- a/README.md +++ b/README.md @@ -144,6 +144,7 @@ interface Props { background?: string; qualityLevel?: number; compressionLevel?: number; + autoConnect?: number; // defaults to true retryDuration?: number; // in milliseconds debug?: boolean; // show logs in the console } diff --git a/src/lib/VncScreen.tsx b/src/lib/VncScreen.tsx index 19c20cf..140caba 100644 --- a/src/lib/VncScreen.tsx +++ b/src/lib/VncScreen.tsx @@ -21,6 +21,7 @@ export interface Props { background?: string; qualityLevel?: number; compressionLevel?: number; + autoConnect?: boolean; retryDuration?: number; debug?: boolean; } @@ -33,7 +34,8 @@ export type VncScreenHandle = { const VncScreen: React.ForwardRefRenderFunction = (props, ref) => { const [rfb, setRfb] = useState(null); - const [connected, setConnected] = useState(false); + const connected = useRef(props.autoConnect ?? true); + const timeouts = useRef>([]); const screen = useRef(null); const [loading, setLoading] = useState(true); @@ -51,6 +53,7 @@ const VncScreen: React.ForwardRefRenderFunction = (props background, qualityLevel, compressionLevel, + autoConnect = true, retryDuration = 3000, debug = false, } = props; @@ -61,19 +64,68 @@ const VncScreen: React.ForwardRefRenderFunction = (props error: (...args: any[]) => { if (debug) console.error(...args); }, }; - const disconnect = () => { - if (!rfb) { - return; + const getConnected = () => { + return connected.current; + } + + const setConnected = (state: boolean) => { + connected.current = state; + } + + const onConnect = () => { + logger.info('Connected to remote VNC.'); + setLoading(false); + }; + + const onDisconnect = () => { + const connected = getConnected(); + console.log('onDisconnect: connected', connected); + if (connected) { + logger.info(`Unexpectedly disconnected from remote VNC, retrying in ${retryDuration / 1000} seconds.`); + + timeouts.current.push(setTimeout(connect, retryDuration)); + } else { + logger.info(`Disconnected from remote VNC.`); } + setLoading(true); + } + + const onCredentialsRequired = (_rfb: RFB) => { + const password = prompt("Password Required:"); + _rfb.sendCredentials({ password: password }); + }; + + const onDesktopName = (e: { detail: { name: string } }) => { + logger.info(`Desktop name is ${e.detail.name}`); + }; - rfb.disconnect(); - setRfb(null); - setConnected(false); + const disconnect = () => { + try { + if (!rfb) { + return; + } + + timeouts.current.forEach(clearTimeout); + rfb.disconnect(); + rfb.removeEventListener('connected', onConnect); + rfb.removeEventListener('disconnect', onDisconnect); + rfb.removeEventListener('credentialsrequired', onCredentialsRequired); + rfb.removeEventListener('desktopname', onDesktopName); + setRfb(null); + setConnected(false); + } catch (err) { + logger.error(err); + setRfb(null); + setConnected(false); + } }; const connect = () => { try { - disconnect(); + console.log('connected', connected); + if (connected && !!rfb) { + disconnect(); + } if (!screen.current) { return; @@ -95,29 +147,15 @@ const VncScreen: React.ForwardRefRenderFunction = (props _rfb.compressionLevel = compressionLevel ?? 2; setRfb(_rfb); - _rfb.addEventListener('connect', () => { - logger.info('Connected to remote VNC.'); - setLoading(false); - }); - - _rfb.addEventListener('disconnect', () => { - if (connected) { - logger.info(`Unexpectedly disconnected from remote VNC, retrying in ${retryDuration / 1000} seconds.`); - setTimeout(connect, retryDuration); - } - logger.info(`Disconnected from remote VNC.`); - setLoading(true); - }); - - _rfb.addEventListener('credentialsrequired', () => { - const password = prompt("Password Required:"); - _rfb.sendCredentials({ password: password }); - }); - - _rfb.addEventListener('desktopname', (e: { detail: { name: string } }) => { - logger.info(`Desktop name is ${e.detail.name}`); - }); + _rfb.addEventListener('connect', onConnect); + + _rfb.addEventListener('disconnect', onDisconnect); + _rfb.addEventListener('credentialsrequired', () => onCredentialsRequired(_rfb)); + + _rfb.addEventListener('desktopname', onDesktopName); + + console.log('Setting connected to true again'); setConnected(true); } catch (err) { logger.error(err); @@ -127,11 +165,13 @@ const VncScreen: React.ForwardRefRenderFunction = (props useImperativeHandle(ref, () => ({ connect, disconnect, - connected, + connected: connected.current, })); useEffect(() => { - connect(); + if (autoConnect) { + connect(); + } return disconnect; // eslint-disable-next-line react-hooks/exhaustive-deps