@@ -145,13 +145,15 @@ export class App extends React.Component<AppProps, AppState> {
145145 customBackgroundSerializer : CustomBackgroundSerializer ;
146146 speedLookUp : Array < number > ;
147147 pushStateTimeoutID : ?TimeoutID ;
148+ languageSelectorRef : { current : any } ;
148149 programBlockEditorRef : { current : any } ;
149150 sequenceInProgress: Array < KeyboardEvent > ;
150151 announcementBuilder: AnnouncementBuilder ;
151152 characterDescriptionBuilder: CharacterDescriptionBuilder ;
152153 designModeCursorDescriptionBuilder: DesignModeCursorDescriptionBuilder ;
153154 programChangeController: ProgramChangeController ;
154155 defaultWorld: WorldName ;
156+ focusLanguageSelector: boolean ;
155157
156158 constructor ( props : any ) {
157159 super ( props ) ;
@@ -180,6 +182,8 @@ export class App extends React.Component<AppProps, AppState> {
180182
181183 this . defaultWorld = 'Sketchpad' ;
182184
185+ this . focusLanguageSelector = false ;
186+
183187 // Initialize startingX, startingY, and startingDirection to the world starting position
184188 const startingX = getWorldProperties ( this . defaultWorld ) . startingX ;
185189 const startingY = getWorldProperties ( this . defaultWorld ) . startingY ;
@@ -247,6 +251,8 @@ export class App extends React.Component<AppProps, AppState> {
247251 this . programChangeController = new ProgramChangeController ( this ,
248252 this . audioManager ) ;
249253
254+ this . languageSelectorRef = React . createRef ( ) ;
255+
250256 this . programBlockEditorRef = React . createRef ( ) ;
251257
252258 const actionsHandler = new ActionsHandler ( this , this . audioManager ,
@@ -333,6 +339,15 @@ export class App extends React.Component<AppProps, AppState> {
333339
334340 // Handlers
335341
342+ handleChangeLanguage = ( language : LanguageTag ) => {
343+ // Changing the language will cause the App to update and for focus to
344+ // be lost. Set this.focusLanguageSelector to true to indicate that we
345+ // want to set focus back to the language selector after the update.
346+ this . focusLanguageSelector = true ;
347+ // Call the provided handler
348+ this . props . onChangeLanguage ( language ) ;
349+ } ;
350+
336351 handleProgramSequenceChange = ( programSequence : ProgramSequence ) = > {
337352 this . setState ( {
338353 programSequence : programSequence
@@ -1278,7 +1293,8 @@ export class App extends React.Component<AppProps, AppState> {
12781293 < div className = 'App__PrivacyButtonLanguageSelectorRow' >
12791294 < LanguageSelector
12801295 value = { this . props . language }
1281- onChange = { this . props . onChangeLanguage }
1296+ onChange = { this . handleChangeLanguage }
1297+ ref = { this . languageSelectorRef }
12821298 />
12831299 < button
12841300 aria-label = { this . props . intl . formatMessage ( { id : 'App.privacyModalToggle.ariaLabel' } ) }
@@ -1881,7 +1897,7 @@ export class App extends React.Component<AppProps, AppState> {
18811897 document . addEventListener ( 'keydown' , this . handleDocumentKeyDown ) ;
18821898 }
18831899
1884- componentDidUpdate ( prevProps : { } , prevState : AppState ) {
1900+ componentDidUpdate ( prevProps : AppProps , prevState : AppState ) {
18851901 if ( this . state . programSequence !== prevState . programSequence
18861902 || this . state . characterState !== prevState . characterState
18871903 || this . state . settings . theme !== prevState . settings . theme
@@ -1981,6 +1997,16 @@ export class App extends React.Component<AppProps, AppState> {
19811997 ) ;
19821998 }
19831999 }
2000+
2001+ // If the language has been changed and this.focusLanguageSelector is
2002+ // set, then set focus to the language selector
2003+ if ( this . props . language !== prevProps . language
2004+ && this . focusLanguageSelector ) {
2005+ if ( this . languageSelectorRef . current ) {
2006+ this . languageSelectorRef . current . focus ( ) ;
2007+ }
2008+ this . focusLanguageSelector = false ;
2009+ }
19842010 }
19852011
19862012 componentWillUnmount ( ) {
0 commit comments