@@ -11,7 +11,7 @@ import "@vscode-elements/elements/dist/vscode-table-row/index.js";
1111import "@vscode-elements/elements/dist/vscode-table-cell/index.js" ;
1212
1313
14- import { Dispatch , useEffect } from "react" ;
14+ import { Dispatch , useCallback , useEffect , useRef } from "react" ;
1515import { useDispatch , useSelector } from "react-redux" ;
1616import { updateCompilerSettings , updateAvailableComplianceLevels } from "./compilerConfigurationViewSlice" ;
1717import { CompilerRequest } from "../../vscode/utils" ;
@@ -54,6 +54,10 @@ const CompilerConfigurationView = (): JSX.Element | null => {
5454 Number ( sourceLevel ) > currentJdkComplianceLevel ||
5555 Number ( targetLevel ) > currentJdkComplianceLevel ;
5656
57+ const complianceRef = useRef < HTMLElement > ( null ) ;
58+ const sourceRef = useRef < HTMLElement > ( null ) ;
59+ const targetRef = useRef < HTMLElement > ( null ) ;
60+
5761 const onMessage = ( event : any ) => {
5862 const message = event . data ;
5963 if ( message . command === "compiler.onDidGetAvailableComplianceLevels" ) {
@@ -73,16 +77,68 @@ const CompilerConfigurationView = (): JSX.Element | null => {
7377 }
7478 } , [ ] ) ;
7579
76- const jdkLevels = ( selectedLevel : string , label : string , onClick : ( value : string ) => void ) => {
80+ // The vscode-single-select element renders its options in the shadow DOM and
81+ // only emits a native `change` event on the host element, so the click handlers
82+ // on the slotted vscode-option children never fire. Listen to `change` instead.
83+ const useSelectChange = ( ref : React . RefObject < HTMLElement | null > , onChange : ( value : string ) => void ) => {
84+ useEffect ( ( ) => {
85+ const el = ref . current ;
86+ if ( ! el ) {
87+ return ;
88+ }
89+ const handler = ( e : Event ) => {
90+ const value = ( e . target as any ) . value ;
91+ if ( value ) {
92+ onChange ( value ) ;
93+ }
94+ } ;
95+ el . addEventListener ( "change" , handler ) ;
96+ return ( ) => el . removeEventListener ( "change" , handler ) ;
97+ } , [ ref , onChange ] ) ;
98+ } ;
99+
100+ const onChangeComplianceLevel = useCallback ( ( value : string ) => {
101+ dispatch ( updateCompilerSettings ( { activeProjectIndex, complianceLevel : value } ) ) ;
102+ } , [ dispatch , activeProjectIndex ] ) ;
103+ const onChangeSourceLevel = useCallback ( ( value : string ) => {
104+ dispatch ( updateCompilerSettings ( { activeProjectIndex, sourceLevel : value } ) ) ;
105+ } , [ dispatch , activeProjectIndex ] ) ;
106+ const onChangeTargetLevel = useCallback ( ( value : string ) => {
107+ dispatch ( updateCompilerSettings ( { activeProjectIndex, targetLevel : value } ) ) ;
108+ } , [ dispatch , activeProjectIndex ] ) ;
109+
110+ useSelectChange ( complianceRef , onChangeComplianceLevel ) ;
111+ useSelectChange ( sourceRef , onChangeSourceLevel ) ;
112+ useSelectChange ( targetRef , onChangeTargetLevel ) ;
113+
114+ // Keep the rendered selection in sync with the redux state. Set the value
115+ // unconditionally (even when the level is "") so the dropdown always reflects
116+ // state instead of keeping the previous project's selection.
117+ useEffect ( ( ) => {
118+ if ( complianceRef . current ) {
119+ ( complianceRef . current as any ) . value = complianceLevel ;
120+ }
121+ } , [ complianceLevel , availableComplianceLevels ] ) ;
122+ useEffect ( ( ) => {
123+ if ( sourceRef . current ) {
124+ ( sourceRef . current as any ) . value = sourceLevel ;
125+ }
126+ } , [ sourceLevel , availableComplianceLevels ] ) ;
127+ useEffect ( ( ) => {
128+ if ( targetRef . current ) {
129+ ( targetRef . current as any ) . value = targetLevel ;
130+ }
131+ } , [ targetLevel , availableComplianceLevels ] ) ;
132+
133+ const jdkLevels = ( selectedLevel : string , label : string ) => {
77134 return availableComplianceLevels . map ( ( level ) => {
78135
79136 return (
80137 < vscode-option
81138 className = "setting-section-option"
82139 key = { `${ label } -${ level } ` }
83140 value = { level }
84- selected = { level === selectedLevel }
85- onClick = { ( ) => onClick ( level ) }
141+ selected = { level === selectedLevel ? true : undefined }
86142 >
87143 < span > { level } </ span >
88144 </ vscode-option >
@@ -104,27 +160,6 @@ const CompilerConfigurationView = (): JSX.Element | null => {
104160 } ) ) ;
105161 } ;
106162
107- const onClickComplianceLevel = ( value : string ) => {
108- dispatch ( updateCompilerSettings ( {
109- activeProjectIndex,
110- complianceLevel : value
111- } ) ) ;
112- } ;
113-
114- const onClickSourceLevel = ( value : string ) => {
115- dispatch ( updateCompilerSettings ( {
116- activeProjectIndex,
117- sourceLevel : value
118- } ) ) ;
119- } ;
120-
121- const onClickTargetLevel = ( value : string ) => {
122- dispatch ( updateCompilerSettings ( {
123- activeProjectIndex,
124- targetLevel : value
125- } ) ) ;
126- } ;
127-
128163 const onClickGenerateDebugInfo = ( e : any ) => {
129164 dispatch ( updateCompilerSettings ( {
130165 activeProjectIndex,
@@ -158,8 +193,8 @@ const CompilerConfigurationView = (): JSX.Element | null => {
158193 < span > Bytecode version:</ span >
159194 </ vscode-table-cell >
160195 < vscode-table-cell className = "flex-center pl-0 pr-0" >
161- < vscode-single-select value = { complianceLevel } >
162- { jdkLevels ( complianceLevel , "compliance" , onClickComplianceLevel ) }
196+ < vscode-single-select ref = { complianceRef } >
197+ { jdkLevels ( complianceLevel , "compliance" ) }
163198 </ vscode-single-select >
164199 </ vscode-table-cell >
165200 </ vscode-table-row >
@@ -168,8 +203,8 @@ const CompilerConfigurationView = (): JSX.Element | null => {
168203 < span > Source compatibility:</ span >
169204 </ vscode-table-cell >
170205 < vscode-table-cell className = "flex-center pl-0 pr-0" >
171- < vscode-single-select value = { sourceLevel } >
172- { jdkLevels ( sourceLevel , "source" , onClickSourceLevel ) }
206+ < vscode-single-select ref = { sourceRef } >
207+ { jdkLevels ( sourceLevel , "source" ) }
173208 </ vscode-single-select >
174209 </ vscode-table-cell >
175210 </ vscode-table-row >
@@ -178,8 +213,8 @@ const CompilerConfigurationView = (): JSX.Element | null => {
178213 < span > Target compatibility:</ span >
179214 </ vscode-table-cell >
180215 < vscode-table-cell className = "flex-center pl-0 pr-0" >
181- < vscode-single-select value = { targetLevel } >
182- { jdkLevels ( targetLevel , "target" , onClickTargetLevel ) }
216+ < vscode-single-select ref = { targetRef } >
217+ { jdkLevels ( targetLevel , "target" ) }
183218 </ vscode-single-select >
184219 </ vscode-table-cell >
185220 </ vscode-table-row >
0 commit comments