@@ -11,7 +11,7 @@ import type { Frame } from '../ui/frame';
1111import type { NavigationEntry } from '../ui/frame/frame-interfaces' ;
1212import type { StyleScope } from '../ui/styling/style-scope' ;
1313import type { AndroidApplication as AndroidApplicationType , iOSApplication as iOSApplicationType } from '.' ;
14- import type { ApplicationEventData , CssChangedEventData , DiscardedErrorEventData , FontScaleChangedEventData , InitRootViewEventData , LaunchEventData , LoadAppCSSEventData , NativeScriptError , OrientationChangedEventData , SystemAppearanceChangedEventData , UnhandledErrorEventData } from './application-interfaces' ;
14+ import type { ApplicationEventData , CssChangedEventData , DiscardedErrorEventData , FontScaleChangedEventData , InitRootViewEventData , LaunchEventData , LoadAppCSSEventData , NativeScriptError , OrientationChangedEventData , SystemAppearanceChangedEventData , LayoutDirectionChangedEventData , UnhandledErrorEventData } from './application-interfaces' ;
1515import { readyInitAccessibilityCssHelper , readyInitFontScale } from '../accessibility/accessibility-common' ;
1616import { getAppMainEntry , isAppInBackground , setAppInBackground , setAppMainEntry } from './helpers-common' ;
1717import { getNativeScriptGlobals } from '../globals/global-utils' ;
@@ -30,6 +30,12 @@ const SYSTEM_APPEARANCE_CSS_CLASSES = [
3030 `${ CSSUtils . CLASS_PREFIX } ${ CoreTypes . SystemAppearance . dark } ` ,
3131] ;
3232
33+ // prettier-ignore
34+ const LAYOUT_DIRECTION_CSS_CLASSES = [
35+ `${ CSSUtils . CLASS_PREFIX } ${ CoreTypes . LayoutDirection . ltr } ` ,
36+ `${ CSSUtils . CLASS_PREFIX } ${ CoreTypes . LayoutDirection . rtl } ` ,
37+ ] ;
38+
3339// SDK Version CSS classes
3440let sdkVersionClasses : string [ ] = [ ] ;
3541
@@ -164,6 +170,12 @@ interface ApplicationEvents {
164170 */
165171 on ( event : 'systemAppearanceChanged' , callback : ( args : SystemAppearanceChangedEventData ) => void , thisArg ?: any ) : void ;
166172
173+ /**
174+ * This event is raised when the operating system layout direction changes
175+ * between ltr and rtl.
176+ */
177+ on ( event : 'layoutDirectionChanged' , callback : ( args : LayoutDirectionChangedEventData ) => void , thisArg ?: any ) : void ;
178+
167179 on ( event : 'fontScaleChanged' , callback : ( args : FontScaleChangedEventData ) => void , thisArg ?: any ) : void ;
168180}
169181
@@ -180,6 +192,7 @@ export class ApplicationCommon {
180192 readonly discardedErrorEvent = 'discardedError' ;
181193 readonly orientationChangedEvent = 'orientationChanged' ;
182194 readonly systemAppearanceChangedEvent = 'systemAppearanceChanged' ;
195+ readonly layoutDirectionChangedEvent = 'layoutDirectionChanged' ;
183196 readonly fontScaleChangedEvent = 'fontScaleChanged' ;
184197 readonly livesyncEvent = 'livesync' ;
185198 readonly loadAppCssEvent = 'loadAppCss' ;
@@ -215,6 +228,21 @@ export class ApplicationCommon {
215228 notify : ApplicationEvents [ 'notify' ] = globalEvents . notify . bind ( globalEvents ) ;
216229 hasListeners : ApplicationEvents [ 'hasListeners' ] = globalEvents . hasListeners . bind ( globalEvents ) ;
217230
231+ private _orientation : 'portrait' | 'landscape' | 'unknown' ;
232+ private _systemAppearance : 'dark' | 'light' | null ;
233+ private _layoutDirection : CoreTypes . LayoutDirectionType | null ;
234+ private _inBackground : boolean = false ;
235+ private _suspended : boolean = false ;
236+ private _cssFile = './app.css' ;
237+
238+ protected mainEntry : NavigationEntry ;
239+
240+ public started = false ;
241+ /**
242+ * Boolean to enable/disable systemAppearanceChanged
243+ */
244+ public autoSystemAppearanceChanged = true ;
245+
218246 /**
219247 * @internal - should not be constructed by the user.
220248 */
@@ -321,6 +349,7 @@ export class ApplicationCommon {
321349 const deviceType = Device . deviceType . toLowerCase ( ) ;
322350 const orientation = this . orientation ( ) ;
323351 const systemAppearance = this . systemAppearance ( ) ;
352+ const layoutDirection = this . layoutDirection ( ) ;
324353
325354 if ( platform ) {
326355 CSSUtils . pushToSystemCssClasses ( `${ CSSUtils . CLASS_PREFIX } ${ platform } ` ) ;
@@ -338,6 +367,10 @@ export class ApplicationCommon {
338367 CSSUtils . pushToSystemCssClasses ( `${ CSSUtils . CLASS_PREFIX } ${ systemAppearance } ` ) ;
339368 }
340369
370+ if ( layoutDirection ) {
371+ CSSUtils . pushToSystemCssClasses ( `${ CSSUtils . CLASS_PREFIX } ${ layoutDirection } ` ) ;
372+ }
373+
341374 rootView . cssClasses . add ( CSSUtils . ROOT_VIEW_CSS_CLASS ) ;
342375 const rootViewCssClasses = CSSUtils . getSystemCssClasses ( ) ;
343376 rootViewCssClasses . forEach ( ( c ) => rootView . cssClasses . add ( c ) ) ;
@@ -447,12 +480,11 @@ export class ApplicationCommon {
447480 bindableResources . set ( res ) ;
448481 }
449482
450- private cssFile = './app.css' ;
451483 /**
452484 * Sets css file name for the application.
453485 */
454486 setCssFileName ( cssFileName : string ) {
455- this . cssFile = cssFileName ;
487+ this . _cssFile = cssFileName ;
456488 this . notify ( < CssChangedEventData > {
457489 eventName : this . cssChangedEvent ,
458490 object : this ,
@@ -464,7 +496,7 @@ export class ApplicationCommon {
464496 * Gets css file name for the application.
465497 */
466498 getCssFileName ( ) : string {
467- return this . cssFile ;
499+ return this . _cssFile ;
468500 }
469501
470502 /**
@@ -507,8 +539,6 @@ export class ApplicationCommon {
507539 throw new Error ( 'run() Not implemented.' ) ;
508540 }
509541
510- private _orientation : 'portrait' | 'landscape' | 'unknown' ;
511-
512542 protected getOrientation ( ) : 'portrait' | 'landscape' | 'unknown' {
513543 // override in platform specific Application class
514544 throw new Error ( 'getOrientation() not implemented' ) ;
@@ -568,8 +598,6 @@ export class ApplicationCommon {
568598 return getNativeScriptGlobals ( ) . launched ;
569599 }
570600
571- private _systemAppearance : 'dark' | 'light' | null ;
572-
573601 protected getSystemAppearance ( ) : 'dark' | 'light' | null {
574602 // override in platform specific Application class
575603 throw new Error ( 'getSystemAppearance() not implemented' ) ;
@@ -595,11 +623,6 @@ export class ApplicationCommon {
595623 return ( this . _systemAppearance ??= this . getSystemAppearance ( ) ) ;
596624 }
597625
598- /**
599- * Boolean to enable/disable systemAppearanceChanged
600- */
601- autoSystemAppearanceChanged = true ;
602-
603626 /**
604627 * enable/disable systemAppearanceChanged
605628 */
@@ -632,6 +655,56 @@ export class ApplicationCommon {
632655 rootView . _onCssStateChange ( ) ;
633656 }
634657
658+ protected getLayoutDirection ( ) : CoreTypes . LayoutDirectionType | null {
659+ // override in platform specific Application class
660+ throw new Error ( 'getLayoutDirection() not implemented' ) ;
661+ }
662+
663+ protected setLayoutDirection ( value : CoreTypes . LayoutDirectionType ) {
664+ if ( this . _layoutDirection === value ) {
665+ return ;
666+ }
667+ this . _layoutDirection = value ;
668+ this . layoutDirectionChanged ( this . getRootView ( ) , value ) ;
669+ this . notify ( < LayoutDirectionChangedEventData > {
670+ eventName : this . layoutDirectionChangedEvent ,
671+ android : this . android ,
672+ ios : this . ios ,
673+ newValue : value ,
674+ object : this ,
675+ } ) ;
676+ }
677+
678+ layoutDirection ( ) : CoreTypes . LayoutDirectionType | null {
679+ // return cached value, or get it from the platform specific override
680+ return ( this . _layoutDirection ??= this . getLayoutDirection ( ) ) ;
681+ }
682+
683+ /**
684+ * Updates root view classes including those of modals
685+ * @param rootView the root view
686+ * @param newLayoutDirection the new layout direction change
687+ */
688+ layoutDirectionChanged ( rootView : View , newLayoutDirection : CoreTypes . LayoutDirectionType ) : void {
689+ if ( ! rootView ) {
690+ return ;
691+ }
692+
693+ const newLayoutDirectionCssClass = `${ CSSUtils . CLASS_PREFIX } ${ newLayoutDirection } ` ;
694+ this . applyCssClass ( rootView , LAYOUT_DIRECTION_CSS_CLASSES , newLayoutDirectionCssClass , true ) ;
695+
696+ const rootModalViews = rootView . _getRootModalViews ( ) ;
697+ rootModalViews . forEach ( ( rootModalView ) => {
698+ this . applyCssClass ( rootModalView as View , LAYOUT_DIRECTION_CSS_CLASSES , newLayoutDirectionCssClass , true ) ;
699+
700+ // Trigger state change for root modal view classes and media queries
701+ rootModalView . _onCssStateChange ( ) ;
702+ } ) ;
703+
704+ // Trigger state change for root view classes and media queries
705+ rootView . _onCssStateChange ( ) ;
706+ }
707+
635708 get inBackground ( ) {
636709 return isAppInBackground ( ) ;
637710 }
@@ -648,8 +721,6 @@ export class ApplicationCommon {
648721 } ) ;
649722 }
650723
651- private _suspended : boolean = false ;
652-
653724 get suspended ( ) {
654725 return this . _suspended ;
655726 }
@@ -667,8 +738,6 @@ export class ApplicationCommon {
667738 } ) ;
668739 }
669740
670- public started = false ;
671-
672741 get android ( ) : AndroidApplicationType {
673742 return undefined ;
674743 }
0 commit comments