11import { ReactElement , useEffect , useRef , useState } from 'react'
2- import { createLanguageClientManager , LanguageClientId , StatusChangeEvent , LanguageClientManager , WillShutdownParams } from '@codingame/monaco-languageclient-wrapper'
2+ import { createLanguageClientManager , LanguageClientId , StatusChangeEvent as WrapperStatusChangeEvent , LanguageClientManager , WillShutdownParams } from '@codingame/monaco-languageclient-wrapper'
33import useIsUserActive from './hooks/useIsUserActive'
44import useShouldShutdownLanguageClient from './hooks/useShouldShutdownLanguageClient'
5+ import { useLastVersion } from './hooks/useLastVersion'
6+
7+ export interface StatusChangeEvent {
8+ status : WrapperStatusChangeEvent [ 'status' ] | 'inactivityShutdown'
9+ }
510
611export interface LanguageClientProps {
712 id : LanguageClientId
@@ -22,29 +27,33 @@ export interface LanguageClientProps {
2227
2328const defaultLibraryUrls : string [ ] = [ ]
2429
30+ const noop = ( ) => null
31+
2532function LanguageClient ( {
2633 id,
2734 sessionId,
2835 languageServerUrl,
2936 useMutualizedProxy,
30- getSecurityToken,
37+ getSecurityToken : _getSecurityToken ,
3138 libraryUrls = defaultLibraryUrls ,
32- onError,
33- onDidChangeStatus,
34- onWillShutdown,
39+ onError : _onError ,
40+ onDidChangeStatus : _onDidChangeStatus ,
41+ onWillShutdown : _onWillShutdown ,
3542 userInactivityDelay = 30 * 1000 ,
3643 userInactivityShutdownDelay = 60 * 1000
3744} : LanguageClientProps ) : ReactElement | null {
38- const onErrorRef = useRef < ( error : Error ) => void > ( )
39- const onDidChangeStatusRef = useRef < ( status : StatusChangeEvent ) => void > ( )
40- const onWillShutdownRef = useRef < ( params : WillShutdownParams ) => void > ( )
45+ const getSecurityToken = useLastVersion ( _getSecurityToken )
46+ const onError = useLastVersion ( _onError ?? noop )
47+ const onDidChangeStatus = useLastVersion ( _onDidChangeStatus ?? noop )
48+ const onWillShutdown = useLastVersion ( _onWillShutdown ?? noop )
49+
4150 const languageClientRef = useRef < LanguageClientManager > ( )
4251
4352 const [ willShutdown , setWillShutdown ] = useState ( false )
4453 const [ counter , setCounter ] = useState ( 1 )
4554
4655 const isUserInactive = useIsUserActive ( userInactivityDelay )
47- const shouldShutdownLanguageClient = useShouldShutdownLanguageClient ( isUserInactive , userInactivityShutdownDelay )
56+ const shouldShutdownLanguageClientForInactivity = useShouldShutdownLanguageClient ( isUserInactive , userInactivityShutdownDelay )
4857 const restartAllowed = ! isUserInactive
4958
5059 useEffect ( ( ) => {
@@ -58,29 +67,22 @@ function LanguageClient ({
5867 useEffect ( ( ) => {
5968 setWillShutdown ( false )
6069
61- if ( shouldShutdownLanguageClient ) {
70+ if ( shouldShutdownLanguageClientForInactivity ) {
71+ onDidChangeStatus ( {
72+ status : 'inactivityShutdown'
73+ } )
6274 return
6375 }
6476
6577 console . info ( `Starting language server for language ${ id } ` )
6678 const languageClient = createLanguageClientManager ( id , sessionId , languageServerUrl , getSecurityToken , libraryUrls , useMutualizedProxy )
6779 languageClientRef . current = languageClient
68- const errorDisposable = languageClient . onError ( ( error : Error ) => {
69- if ( onErrorRef . current != null ) {
70- onErrorRef . current ( error )
71- }
72- } )
73- const statusChangeDisposable = languageClient . onDidChangeStatus ( ( status : StatusChangeEvent ) => {
74- if ( onDidChangeStatusRef . current != null ) {
75- onDidChangeStatusRef . current ( status )
76- }
77- } )
80+ const errorDisposable = languageClient . onError ( onError )
81+ const statusChangeDisposable = languageClient . onDidChangeStatus ( onDidChangeStatus )
7882 const startTimeout = setTimeout ( ( ) => languageClient . start ( ) )
7983
8084 languageClient . onWillShutdown ( ( params : WillShutdownParams ) => {
81- if ( onWillShutdownRef . current != null ) {
82- onWillShutdownRef . current ( params )
83- }
85+ onWillShutdown ( params )
8486 setWillShutdown ( true )
8587 } )
8688
@@ -95,19 +97,7 @@ function LanguageClient ({
9597 console . error ( 'Unable to dispose language client' , err )
9698 } )
9799 }
98- } , [ getSecurityToken , id , languageServerUrl , libraryUrls , sessionId , counter , useMutualizedProxy , shouldShutdownLanguageClient ] )
99-
100- useEffect ( ( ) => {
101- onErrorRef . current = onError
102- } , [ onError ] )
103-
104- useEffect ( ( ) => {
105- onDidChangeStatusRef . current = onDidChangeStatus
106- } , [ onDidChangeStatus ] )
107-
108- useEffect ( ( ) => {
109- onWillShutdownRef . current = onWillShutdown
110- } , [ onWillShutdown ] )
100+ } , [ getSecurityToken , id , languageServerUrl , libraryUrls , sessionId , counter , useMutualizedProxy , shouldShutdownLanguageClientForInactivity , onError , onDidChangeStatus , onWillShutdown ] )
111101
112102 return null
113103}
0 commit comments