@@ -23,60 +23,127 @@ export type TerminalWorkspaceReadyState = {
2323 readonly terminalSessions : ReadonlyArray < ActiveTerminalSession >
2424}
2525
26- type PersistedSelectionRef = {
27- current : string | null
26+ type ProjectActiveTerminalSelection = {
27+ readonly projectKey : string
28+ readonly sessionId : string
2829}
2930
31+ type ProjectActiveTerminalPersistenceRequest = ProjectActiveTerminalSelection & {
32+ readonly selectionKey : string
33+ }
34+
35+ type ProjectActiveTerminalPersistenceState = {
36+ readonly inFlightRequest : ProjectActiveTerminalPersistenceRequest | null
37+ readonly latestRequest : ProjectActiveTerminalPersistenceRequest | null
38+ readonly persistedSelectionKey : string | null
39+ }
40+
41+ type ProjectActiveTerminalPersistenceRef = {
42+ current : ProjectActiveTerminalPersistenceState
43+ }
44+
45+ type SetProjectActiveTerminalSessionEffect = ReturnType < typeof setProjectActiveTerminalSession >
46+ type ProjectActiveTerminalPersistResult = Either . Either <
47+ Effect . Effect . Success < SetProjectActiveTerminalSessionEffect > ,
48+ Effect . Effect . Error < SetProjectActiveTerminalSessionEffect >
49+ >
50+
3051export const projectActiveTerminalSelection = (
3152 active : ActiveTerminalSession | null
32- ) : { readonly projectKey : string ; readonly sessionId : string } | null =>
53+ ) : ProjectActiveTerminalSelection | null =>
3354 active ?. browserProjectKey === undefined || active . pendingConnection !== undefined
3455 ? null
3556 : { projectKey : active . browserProjectKey , sessionId : active . session . id }
3657
3758const projectActiveTerminalSelectionKey = (
38- selection : { readonly projectKey : string ; readonly sessionId : string }
59+ selection : ProjectActiveTerminalSelection
3960) : string => `${ selection . projectKey } \0${ selection . sessionId } `
4061
41- const clearFailedPersistedSelection = (
42- persistedSelectionRef : PersistedSelectionRef ,
43- selectionKey : string
62+ const emptyProjectActiveTerminalPersistenceState = ( ) : ProjectActiveTerminalPersistenceState => ( {
63+ inFlightRequest : null ,
64+ latestRequest : null ,
65+ persistedSelectionKey : null
66+ } )
67+
68+ export const createProjectActiveTerminalPersistenceRef = ( ) : ProjectActiveTerminalPersistenceRef => ( {
69+ current : emptyProjectActiveTerminalPersistenceState ( )
70+ } )
71+
72+ const projectActiveTerminalPersistenceRequest = (
73+ selection : ProjectActiveTerminalSelection
74+ ) : ProjectActiveTerminalPersistenceRequest => ( {
75+ ...selection ,
76+ selectionKey : projectActiveTerminalSelectionKey ( selection )
77+ } )
78+
79+ const completeProjectActiveTerminalPersistRequest = (
80+ persistedSelectionRef : ProjectActiveTerminalPersistenceRef ,
81+ request : ProjectActiveTerminalPersistenceRequest ,
82+ result : ProjectActiveTerminalPersistResult
4483) : Effect . Effect < void > =>
4584 Effect . sync ( ( ) => {
46- if ( persistedSelectionRef . current === selectionKey ) {
47- persistedSelectionRef . current = null
85+ if ( persistedSelectionRef . current . inFlightRequest ?. selectionKey !== request . selectionKey ) {
86+ return
87+ }
88+ const persistedSelectionKey = Either . match ( result , {
89+ onLeft : ( ) => persistedSelectionRef . current . persistedSelectionKey ,
90+ onRight : ( ) => request . selectionKey
91+ } )
92+ persistedSelectionRef . current = {
93+ ...persistedSelectionRef . current ,
94+ inFlightRequest : null ,
95+ persistedSelectionKey
96+ }
97+ const latestRequest = persistedSelectionRef . current . latestRequest
98+ if ( latestRequest !== null && latestRequest . selectionKey !== request . selectionKey ) {
99+ runProjectActiveTerminalPersistRequest ( persistedSelectionRef )
48100 }
49101 } )
50102
51- const persistProjectActiveTerminalSelection = (
52- state : TerminalWorkspaceState ,
53- persistedSelectionRef : PersistedSelectionRef
103+ const runProjectActiveTerminalPersistRequest = (
104+ persistedSelectionRef : ProjectActiveTerminalPersistenceRef
54105) : void => {
55- const active = projectActiveTerminalSelection ( activeTerminalSession ( state ) )
56- if ( active === null ) {
106+ const { inFlightRequest, latestRequest, persistedSelectionKey } = persistedSelectionRef . current
107+ if (
108+ inFlightRequest !== null ||
109+ latestRequest === null ||
110+ latestRequest . selectionKey === persistedSelectionKey
111+ ) {
57112 return
58113 }
59- const selectionKey = projectActiveTerminalSelectionKey ( active )
60- if ( persistedSelectionRef . current === selectionKey ) {
61- return
114+ persistedSelectionRef . current = {
115+ ... persistedSelectionRef . current ,
116+ inFlightRequest : latestRequest
62117 }
63- persistedSelectionRef . current = selectionKey
64118 void Effect . runPromise (
65- setProjectActiveTerminalSession ( active . projectKey , active . sessionId ) . pipe (
119+ setProjectActiveTerminalSession ( latestRequest . projectKey , latestRequest . sessionId ) . pipe (
66120 Effect . either ,
67121 Effect . flatMap ( ( result ) =>
68- Either . match ( result , {
69- onLeft : ( ) => clearFailedPersistedSelection ( persistedSelectionRef , selectionKey ) ,
70- onRight : ( ) => Effect . void
71- } )
122+ completeProjectActiveTerminalPersistRequest ( persistedSelectionRef , latestRequest , result )
72123 )
73124 )
74125 )
75126}
76127
128+ export const persistProjectActiveTerminalSelection = (
129+ state : TerminalWorkspaceState ,
130+ persistedSelectionRef : ProjectActiveTerminalPersistenceRef
131+ ) : void => {
132+ const active = projectActiveTerminalSelection ( activeTerminalSession ( state ) )
133+ if ( active === null ) {
134+ return
135+ }
136+ const latestRequest = projectActiveTerminalPersistenceRequest ( active )
137+ persistedSelectionRef . current = {
138+ ...persistedSelectionRef . current ,
139+ latestRequest
140+ }
141+ runProjectActiveTerminalPersistRequest ( persistedSelectionRef )
142+ }
143+
77144export const useTerminalWorkspaceState = ( ) : TerminalWorkspaceReadyState => {
78145 const [ terminalWorkspace , setTerminalWorkspace ] = useState < TerminalWorkspaceState > ( readStoredTerminalWorkspace )
79- const persistedSelectionRef = useRef < string | null > ( null )
146+ const persistedSelectionRef = useRef ( emptyProjectActiveTerminalPersistenceState ( ) )
80147 const addTerminalSession = useCallback ( ( session : ActiveTerminalSession ) => {
81148 setTerminalWorkspace ( ( state ) => addTerminalSessionState ( state , session ) )
82149 } , [ ] )
0 commit comments