11import { ReactElement , useEffect , useRef , useState } from 'react'
22import { createLanguageClientManager , LanguageClientId , StatusChangeEvent , LanguageClientManager , WillShutdownParams } from '@codingame/monaco-languageclient-wrapper'
3+ import useIsUserActive from './hooks/useIsUserActive'
4+ import useShouldShutdownLanguageClient from './hooks/useShouldShutdownLanguageClient'
35
46export interface LanguageClientProps {
57 id : LanguageClientId
@@ -12,8 +14,10 @@ export interface LanguageClientProps {
1214 onDidChangeStatus ?: ( status : StatusChangeEvent ) => void
1315 /** The language client will be shutdown by the server */
1416 onWillShutdown ?: ( status : WillShutdownParams ) => void
15- /** Allows the client to reconnect to another server when it receives the willShutdown notification */
16- restartAllowed ?: boolean
17+ /** User is considered inactive when there is no event during this delay (default 30 seconds) or when the tab is blurred */
18+ userInactivityDelay ?: number
19+ /** Shutdown the language client when the user stay inactive during this duration (default 60 seconds) */
20+ userInactivityShutdownDelay ?: number
1721}
1822
1923const defaultLibraryUrls : string [ ] = [ ]
@@ -28,7 +32,8 @@ function LanguageClient ({
2832 onError,
2933 onDidChangeStatus,
3034 onWillShutdown,
31- restartAllowed = true
35+ userInactivityDelay = 30 * 1000 ,
36+ userInactivityShutdownDelay = 60 * 1000
3237} : LanguageClientProps ) : ReactElement | null {
3338 const onErrorRef = useRef < ( error : Error ) => void > ( )
3439 const onDidChangeStatusRef = useRef < ( status : StatusChangeEvent ) => void > ( )
@@ -38,6 +43,10 @@ function LanguageClient ({
3843 const [ willShutdown , setWillShutdown ] = useState ( false )
3944 const [ counter , setCounter ] = useState ( 1 )
4045
46+ const isUserInactive = useIsUserActive ( userInactivityDelay )
47+ const shouldShutdownLanguageClient = useShouldShutdownLanguageClient ( isUserInactive , userInactivityShutdownDelay )
48+ const restartAllowed = ! isUserInactive
49+
4150 useEffect ( ( ) => {
4251 if ( willShutdown && restartAllowed ) {
4352 console . info ( 'Restarting language client because the current instance will be shutdown' )
@@ -49,6 +58,10 @@ function LanguageClient ({
4958 useEffect ( ( ) => {
5059 setWillShutdown ( false )
5160
61+ if ( shouldShutdownLanguageClient ) {
62+ return
63+ }
64+
5265 console . info ( `Starting language server for language ${ id } ` )
5366 const languageClient = createLanguageClientManager ( id , sessionId , languageServerUrl , getSecurityToken , libraryUrls , useMutualizedProxy )
5467 languageClientRef . current = languageClient
@@ -82,7 +95,7 @@ function LanguageClient ({
8295 console . error ( 'Unable to dispose language client' , err )
8396 } )
8497 }
85- } , [ getSecurityToken , id , languageServerUrl , libraryUrls , sessionId , counter , useMutualizedProxy ] )
98+ } , [ getSecurityToken , id , languageServerUrl , libraryUrls , sessionId , counter , useMutualizedProxy , shouldShutdownLanguageClient ] )
8699
87100 useEffect ( ( ) => {
88101 onErrorRef . current = onError
0 commit comments