@@ -19,6 +19,7 @@ import React, { ReactNode } from 'react'
1919import { createStyles , Theme , withStyles } from '@material-ui/core'
2020import { StyleRules } from '@material-ui/core/styles'
2121import RFB from '@novnc/novnc/core/rfb'
22+ import PasswordDialog from './PasswordDialog'
2223
2324const useStyles = ( theme : Theme ) : StyleRules => createStyles (
2425 {
@@ -47,14 +48,35 @@ interface LiveViewProps {
4748 * smaller than its container, or handled according to `clipViewport` if it
4849 * is larger. Default is false.
4950 */
50- scaleViewport ?: boolean
51+ scaleViewport ?: boolean ,
52+ /**
53+ * Callback to close the Live View when the PasswordDialog is prompted and
54+ * the user clicks 'Cancel'
55+ */
56+ onClose : ( ) => void
5157}
5258
53- class LiveView extends React . Component < LiveViewProps , { } > {
59+ interface PasswordDialogState {
60+ open : boolean ,
61+ message : string
62+ }
5463
64+ class LiveView extends React . Component < LiveViewProps , PasswordDialogState > {
5565 rfb : any = null
5666 canvas : any = null
5767
68+ constructor ( props ) {
69+ super ( props )
70+ this . state = {
71+ open : false ,
72+ message : ''
73+ }
74+ }
75+
76+ handlePasswordDialog = ( state : boolean ) : void => {
77+ this . setState ( { open : state } )
78+ }
79+
5880 disconnect = ( ) => {
5981 if ( ! this . rfb ) {
6082 return
@@ -74,6 +96,8 @@ class LiveView extends React.Component<LiveViewProps, {}> {
7496 this . rfb = new RFB ( this . canvas , this . props . url , { } )
7597 this . rfb . scaleViewport = this . props . scaleViewport
7698 this . rfb . background = 'rgb(247,248,248)'
99+ this . rfb . addEventListener ( 'credentialsrequired' , this . handleCredentials )
100+ this . rfb . addEventListener ( 'securityfailure' , this . securityFailed )
77101 }
78102
79103 registerChild = ref => {
@@ -96,6 +120,30 @@ class LiveView extends React.Component<LiveViewProps, {}> {
96120 this . rfb . scaleViewport = this . props . scaleViewport
97121 }
98122
123+ securityFailed = ( event : any ) => {
124+ let errorMessage
125+ if ( 'reason' in event . detail ) {
126+ errorMessage =
127+ 'Connection has been rejected with reason: ' + event . detail . reason
128+ } else {
129+ errorMessage = 'New connection has been rejected'
130+ }
131+ this . setState ( { message : errorMessage } )
132+ this . connect ( )
133+ }
134+
135+ handleCredentials = ( ) => {
136+ this . handlePasswordDialog ( true )
137+ }
138+
139+ handleCredentialsEntered = ( password : string ) => {
140+ this . rfb . sendCredentials ( { username : '' , password : password } )
141+ }
142+
143+ handlePasswordDialogClose = ( ) => {
144+ this . props . onClose ( )
145+ }
146+
99147 handleMouseEnter = ( ) => {
100148 if ( ! this . rfb ) {
101149 return
@@ -113,6 +161,8 @@ class LiveView extends React.Component<LiveViewProps, {}> {
113161 }
114162
115163 render ( ) : ReactNode {
164+ const { open, message } = this . state
165+
116166 return (
117167 < div
118168 style = {
@@ -124,7 +174,16 @@ class LiveView extends React.Component<LiveViewProps, {}> {
124174 ref = { this . registerChild }
125175 onMouseEnter = { this . handleMouseEnter }
126176 onMouseLeave = { this . handleMouseLeave }
127- />
177+ >
178+ < PasswordDialog title = { 'LiveView (VNC) Password' }
179+ open = { open }
180+ setOpen = { this . handlePasswordDialog }
181+ onConfirm = { this . handleCredentialsEntered }
182+ onCancel = { this . handlePasswordDialogClose }
183+ >
184+ { message }
185+ </ PasswordDialog >
186+ </ div >
128187 )
129188 }
130189}
0 commit comments