11import  { 
2-   CommandRegistry , 
2+   ApplicationError , 
33  Disposable , 
44  Emitter , 
55  MessageService , 
66  nls , 
77}  from  '@theia/core' ; 
8+ import  {  Deferred  }  from  '@theia/core/lib/common/promise-util' ; 
89import  {  inject ,  injectable  }  from  '@theia/core/shared/inversify' ; 
10+ import  {  NotificationManager  }  from  '@theia/messages/lib/browser/notifications-manager' ; 
11+ import  {  MessageType  }  from  '@theia/core/lib/common/message-service-protocol' ; 
912import  {  Board ,  Port  }  from  '../common/protocol' ; 
1013import  { 
1114  Monitor , 
@@ -23,21 +26,31 @@ import { BoardsServiceProvider } from './boards/boards-service-provider';
2326export  class  MonitorManagerProxyClientImpl 
2427  implements  MonitorManagerProxyClient 
2528{ 
29+   @inject ( MessageService ) 
30+   private  readonly  messageService : MessageService ; 
31+   // This is necessary to call the backend methods from the frontend 
32+   @inject ( MonitorManagerProxyFactory ) 
33+   private  readonly  server : MonitorManagerProxyFactory ; 
34+   @inject ( BoardsServiceProvider ) 
35+   private  readonly  boardsServiceProvider : BoardsServiceProvider ; 
36+   @inject ( NotificationManager ) 
37+   private  readonly  notificationManager : NotificationManager ; 
38+ 
2639  // When pluggable monitor messages are received from the backend 
2740  // this event is triggered. 
2841  // Ideally a frontend component is connected to this event 
2942  // to update the UI. 
30-   protected  readonly  onMessagesReceivedEmitter  =  new  Emitter < { 
43+   private  readonly  onMessagesReceivedEmitter  =  new  Emitter < { 
3144    messages : string [ ] ; 
3245  } > ( ) ; 
3346  readonly  onMessagesReceived  =  this . onMessagesReceivedEmitter . event ; 
3447
35-   protected  readonly  onMonitorSettingsDidChangeEmitter  = 
48+   private  readonly  onMonitorSettingsDidChangeEmitter  = 
3649    new  Emitter < MonitorSettings > ( ) ; 
3750  readonly  onMonitorSettingsDidChange  = 
3851    this . onMonitorSettingsDidChangeEmitter . event ; 
3952
40-   protected  readonly  onMonitorShouldResetEmitter  =  new  Emitter ( ) ; 
53+   private  readonly  onMonitorShouldResetEmitter  =  new  Emitter < void > ( ) ; 
4154  readonly  onMonitorShouldReset  =  this . onMonitorShouldResetEmitter . event ; 
4255
4356  // WebSocket used to handle pluggable monitor communication between 
@@ -51,29 +64,16 @@ export class MonitorManagerProxyClientImpl
5164    return  this . wsPort ; 
5265  } 
5366
54-   constructor ( 
55-     @inject ( MessageService ) 
56-     protected  messageService : MessageService , 
57- 
58-     // This is necessary to call the backend methods from the frontend 
59-     @inject ( MonitorManagerProxyFactory ) 
60-     protected  server : MonitorManagerProxyFactory , 
61- 
62-     @inject ( CommandRegistry ) 
63-     protected  readonly  commandRegistry : CommandRegistry , 
64- 
65-     @inject ( BoardsServiceProvider ) 
66-     protected  readonly  boardsServiceProvider : BoardsServiceProvider 
67-   )  { } 
68- 
6967  /** 
7068   * Connects a localhost WebSocket using the specified port. 
7169   * @param  addressPort port of the WebSocket 
7270   */ 
7371  async  connect ( addressPort : number ) : Promise < void >  { 
74-     if  ( ! ! this . webSocket )  { 
75-       if  ( this . wsPort  ===  addressPort )  return ; 
76-       else  this . disconnect ( ) ; 
72+     if  ( this . webSocket )  { 
73+       if  ( this . wsPort  ===  addressPort )  { 
74+         return ; 
75+       } 
76+       this . disconnect ( ) ; 
7777    } 
7878    try  { 
7979      this . webSocket  =  new  WebSocket ( `ws://localhost:${ addressPort }  ) ; 
@@ -87,6 +87,9 @@ export class MonitorManagerProxyClientImpl
8787      return ; 
8888    } 
8989
90+     const  opened  =  new  Deferred < void > ( ) ; 
91+     this . webSocket . onopen  =  ( )  =>  opened . resolve ( ) ; 
92+     this . webSocket . onerror  =  ( )  =>  opened . reject ( ) ; 
9093    this . webSocket . onmessage  =  ( message )  =>  { 
9194      const  parsedMessage  =  JSON . parse ( message . data ) ; 
9295      if  ( Array . isArray ( parsedMessage ) ) 
@@ -99,19 +102,26 @@ export class MonitorManagerProxyClientImpl
99102      } 
100103    } ; 
101104    this . wsPort  =  addressPort ; 
105+     return  opened . promise ; 
102106  } 
103107
104108  /** 
105109   * Disconnects the WebSocket if connected. 
106110   */ 
107111  disconnect ( ) : void { 
108-     if  ( ! this . webSocket )  return ; 
112+     if  ( ! this . webSocket )  { 
113+       return ; 
114+     } 
109115    this . onBoardsConfigChanged ?. dispose ( ) ; 
110116    this . onBoardsConfigChanged  =  undefined ; 
111117    try  { 
112-       this . webSocket ? .close ( ) ; 
118+       this . webSocket . close ( ) ; 
113119      this . webSocket  =  undefined ; 
114-     }  catch  { 
120+     }  catch  ( err )  { 
121+       console . error ( 
122+         'Could not close the websocket connection for the monitor.' , 
123+         err 
124+       ) ; 
115125      this . messageService . error ( 
116126        nls . localize ( 
117127          'arduino/monitor/unableToCloseWebSocket' , 
@@ -126,6 +136,7 @@ export class MonitorManagerProxyClientImpl
126136  } 
127137
128138  async  startMonitor ( settings ?: PluggableMonitorSettings ) : Promise < void >  { 
139+     await  this . boardsServiceProvider . reconciled ; 
129140    this . lastConnectedBoard  =  { 
130141      selectedBoard : this . boardsServiceProvider . boardsConfig . selectedBoard , 
131142      selectedPort : this . boardsServiceProvider . boardsConfig . selectedPort , 
@@ -150,11 +161,11 @@ export class MonitorManagerProxyClientImpl
150161                  ? Port . keyOf ( this . lastConnectedBoard . selectedPort ) 
151162                  : undefined ) 
152163            )  { 
153-               this . onMonitorShouldResetEmitter . fire ( null ) ; 
154164              this . lastConnectedBoard  =  { 
155165                selectedBoard : selectedBoard , 
156166                selectedPort : selectedPort , 
157167              } ; 
168+               this . onMonitorShouldResetEmitter . fire ( ) ; 
158169            }  else  { 
159170              // a board is plugged and it's the same as prev, rerun "this.startMonitor" to 
160171              // recreate the listener callback 
@@ -167,7 +178,14 @@ export class MonitorManagerProxyClientImpl
167178    const  {  selectedBoard,  selectedPort }  = 
168179      this . boardsServiceProvider . boardsConfig ; 
169180    if  ( ! selectedBoard  ||  ! selectedBoard . fqbn  ||  ! selectedPort )  return ; 
170-     await  this . server ( ) . startMonitor ( selectedBoard ,  selectedPort ,  settings ) ; 
181+     try  { 
182+       this . clearVisibleNotification ( ) ; 
183+       await  this . server ( ) . startMonitor ( selectedBoard ,  selectedPort ,  settings ) ; 
184+     }  catch  ( err )  { 
185+       const  message  =  ApplicationError . is ( err )  ? err . message  : String ( err ) ; 
186+       this . previousNotificationId  =  this . notificationId ( message ) ; 
187+       this . messageService . error ( message ) ; 
188+     } 
171189  } 
172190
173191  getCurrentSettings ( board : Board ,  port : Port ) : Promise < MonitorSettings >  { 
@@ -199,4 +217,24 @@ export class MonitorManagerProxyClientImpl
199217      } ) 
200218    ) ; 
201219  } 
220+ 
221+   /** 
222+    * This is the internal (Theia) ID of the notification that is currently visible. 
223+    * It's stored here as a field to be able to close it before starting a new monitor connection. It's a hack. 
224+    */ 
225+   private  previousNotificationId : string  |  undefined ; 
226+   private  clearVisibleNotification ( ) : void { 
227+     if  ( this . previousNotificationId )  { 
228+       this . notificationManager . clear ( this . previousNotificationId ) ; 
229+       this . previousNotificationId  =  undefined ; 
230+     } 
231+   } 
232+ 
233+   private  notificationId ( message : string ,  ...actions : string [ ] ) : string  { 
234+     return  this . notificationManager [ 'getMessageId' ] ( { 
235+       text : message , 
236+       actions, 
237+       type : MessageType . Error , 
238+     } ) ; 
239+   } 
202240} 
0 commit comments