@@ -3,14 +3,28 @@ import { Appearance, Platform, StatusBar, useColorScheme } from "react-native";
33import NativeModule from "./specs/NativeEdgeToEdgeModule" ;
44import { SystemBarsEntry , SystemBarsProps , SystemBarStyle } from "./types" ;
55
6- type MergeableBarStyle = "light" | "dark" | undefined ;
6+ type ResolvedBarStyle = "light" | "dark" | undefined ;
77
8- function getColorScheme ( ) : "light" | "dark" {
9- return Appearance ?. getColorScheme ( ) ?? "light" ;
8+ function isLightColorScheme ( ) {
9+ const colorScheme = Appearance ?. getColorScheme ( ) ?? "light" ;
10+ return colorScheme === "light" ;
11+ }
12+
13+ function resolveSystemBarStyle (
14+ style : SystemBarStyle | undefined ,
15+ ) : ResolvedBarStyle {
16+ switch ( style ) {
17+ case "auto" :
18+ return isLightColorScheme ( ) ? "dark" : "light" ;
19+ case "inverted" :
20+ return isLightColorScheme ( ) ? "light" : "dark" ;
21+ default :
22+ return style ;
23+ }
1024}
1125
1226function toNativeBarStyle (
13- style : MergeableBarStyle ,
27+ style : ResolvedBarStyle ,
1428) : "default" | "light-content" | "dark-content" {
1529 return style === "light" || style === "dark" ? `${ style } -content` : "default" ;
1630}
@@ -43,26 +57,23 @@ function mergeEntriesStack(entriesStack: SystemBarsEntry[]) {
4357 ) ;
4458}
4559
60+ function resolveProps ( { hidden, style } : SystemBarsProps ) {
61+ const compactStyle = typeof style === "string" ;
62+ const compactHidden = typeof hidden === "boolean" ;
63+
64+ return {
65+ statusBarStyle : compactStyle ? style : style ?. statusBar ,
66+ navigationBarStyle : compactStyle ? style : style ?. navigationBar ,
67+ statusBarHidden : compactHidden ? hidden : hidden ?. statusBar ,
68+ navigationBarHidden : compactHidden ? hidden : hidden ?. navigationBar ,
69+ } ;
70+ }
71+
4672/**
4773 * Returns an object to insert in the props stack from the props.
4874 */
4975function createStackEntry ( props : SystemBarsProps ) : SystemBarsEntry {
50- return {
51- statusBarStyle :
52- typeof props . style === "string" ? props . style : props . style ?. statusBar ,
53- navigationBarStyle :
54- typeof props . style === "string"
55- ? props . style
56- : props . style ?. navigationBar ,
57- statusBarHidden :
58- typeof props . hidden === "boolean"
59- ? props . hidden
60- : props . hidden ?. statusBar ,
61- navigationBarHidden :
62- typeof props . hidden === "boolean"
63- ? props . hidden
64- : props . hidden ?. navigationBar ,
65- } ;
76+ return resolveProps ( props ) ;
6677}
6778
6879const entriesStack : SystemBarsEntry [ ] = [ ] ;
@@ -71,9 +82,9 @@ const entriesStack: SystemBarsEntry[] = [];
7182let updateImmediate : NodeJS . Immediate | null = null ;
7283
7384// The current merged values from the entries stack.
74- let currentMergedEntries : {
75- statusBarStyle : MergeableBarStyle ;
76- navigationBarStyle : MergeableBarStyle ;
85+ const currentValues : {
86+ statusBarStyle : ResolvedBarStyle ;
87+ navigationBarStyle : ResolvedBarStyle ;
7788 statusBarHidden : boolean ;
7889 navigationBarHidden : boolean ;
7990} = {
@@ -83,6 +94,53 @@ let currentMergedEntries: {
8394 navigationBarHidden : false ,
8495} ;
8596
97+ function setStatusBarStyle ( style : ResolvedBarStyle ) {
98+ if ( style !== currentValues . statusBarStyle ) {
99+ currentValues . statusBarStyle = style ;
100+
101+ const nativeStyle = toNativeBarStyle ( style ) ;
102+
103+ if ( Platform . OS === "android" ) {
104+ NativeModule ?. setStatusBarStyle ( nativeStyle ) ;
105+ } else if ( Platform . OS === "ios" ) {
106+ StatusBar . setBarStyle ( nativeStyle , true ) ;
107+ }
108+ }
109+ }
110+
111+ function setNavigationBarStyle ( style : ResolvedBarStyle ) {
112+ if ( style !== currentValues . navigationBarStyle ) {
113+ currentValues . navigationBarStyle = style ;
114+
115+ if ( Platform . OS === "android" ) {
116+ const nativeStyle = toNativeBarStyle ( style ) ;
117+ NativeModule ?. setNavigationBarStyle ( nativeStyle ) ;
118+ }
119+ }
120+ }
121+
122+ function setStatusBarHidden ( hidden : boolean ) {
123+ if ( hidden !== currentValues . statusBarHidden ) {
124+ currentValues . statusBarHidden = hidden ;
125+
126+ if ( Platform . OS === "android" ) {
127+ NativeModule ?. setStatusBarHidden ( hidden ) ;
128+ } else if ( Platform . OS === "ios" ) {
129+ StatusBar . setHidden ( hidden , "fade" ) ; // 'slide' doesn't work in this context
130+ }
131+ }
132+ }
133+
134+ function setNavigationBarHidden ( hidden : boolean ) {
135+ if ( hidden !== currentValues . navigationBarHidden ) {
136+ currentValues . navigationBarHidden = hidden ;
137+
138+ if ( Platform . OS === "android" ) {
139+ NativeModule ?. setNavigationBarHidden ( hidden ) ;
140+ }
141+ }
142+ }
143+
86144/**
87145 * Updates the native system bars with the entries from the stack.
88146 */
@@ -93,59 +151,20 @@ function updateEntriesStack() {
93151 }
94152
95153 updateImmediate = setImmediate ( ( ) => {
96- const isLightColorScheme = getColorScheme ( ) === "light" ;
97- const autoBarStyle = isLightColorScheme ? "dark" : "light" ;
98- const invertedBarStyle = isLightColorScheme ? "light" : "dark" ;
99-
100154 const mergedEntries = mergeEntriesStack ( entriesStack ) ;
101-
102- const statusBarStyle : MergeableBarStyle =
103- mergedEntries . statusBarStyle === "auto"
104- ? autoBarStyle
105- : mergedEntries . statusBarStyle === "inverted"
106- ? invertedBarStyle
107- : mergedEntries . statusBarStyle ;
108-
109- const navigationBarStyle : MergeableBarStyle =
110- mergedEntries . navigationBarStyle === "auto"
111- ? autoBarStyle
112- : mergedEntries . navigationBarStyle === "inverted"
113- ? invertedBarStyle
114- : mergedEntries . navigationBarStyle ;
115-
116155 const { statusBarHidden, navigationBarHidden } = mergedEntries ;
117156
118- if ( statusBarStyle !== currentMergedEntries . statusBarStyle ) {
119- const style = toNativeBarStyle ( statusBarStyle ) ;
120-
121- Platform . OS === "android"
122- ? NativeModule ?. setStatusBarStyle ( style )
123- : StatusBar . setBarStyle ( style , true ) ;
124- }
125-
126- if ( statusBarHidden !== currentMergedEntries . statusBarHidden ) {
127- Platform . OS === "android"
128- ? NativeModule ?. setStatusBarHidden ( statusBarHidden )
129- : StatusBar . setHidden ( statusBarHidden , "fade" ) ; // 'slide' doesn't work in this context
130- }
131-
132- if ( Platform . OS === "android" ) {
133- if ( navigationBarStyle !== currentMergedEntries . navigationBarStyle ) {
134- const style = toNativeBarStyle ( navigationBarStyle ) ;
135- NativeModule ?. setNavigationBarStyle ( style ) ;
136- }
137-
138- if ( navigationBarHidden !== currentMergedEntries . navigationBarHidden ) {
139- NativeModule ?. setNavigationBarHidden ( navigationBarHidden ) ;
140- }
141- }
157+ const statusBarStyle = resolveSystemBarStyle (
158+ mergedEntries . statusBarStyle ,
159+ ) ;
160+ const navigationBarStyle = resolveSystemBarStyle (
161+ mergedEntries . navigationBarStyle ,
162+ ) ;
142163
143- currentMergedEntries = {
144- statusBarStyle,
145- navigationBarStyle,
146- statusBarHidden,
147- navigationBarHidden,
148- } ;
164+ setStatusBarStyle ( statusBarStyle ) ;
165+ setNavigationBarStyle ( navigationBarStyle ) ;
166+ setStatusBarHidden ( statusBarHidden ) ;
167+ setNavigationBarHidden ( navigationBarHidden ) ;
149168 } ) ;
150169 }
151170}
@@ -195,14 +214,48 @@ function replaceStackEntry(
195214 return newEntry ;
196215}
197216
198- export function SystemBars ( { hidden, style } : SystemBarsProps ) {
199- const statusBarStyle = typeof style === "string" ? style : style ?. statusBar ;
200- const navigationBarStyle =
201- typeof style === "string" ? style : style ?. navigationBar ;
202- const statusBarHidden =
203- typeof hidden === "boolean" ? hidden : hidden ?. statusBar ;
204- const navigationBarHidden =
205- typeof hidden === "boolean" ? hidden : hidden ?. navigationBar ;
217+ /**
218+ * Set the SystemBars style.
219+ *
220+ * @param style SystemBars style to set.
221+ */
222+ function setStyle ( style : SystemBarsProps [ "style" ] ) {
223+ const props = resolveProps ( { style } ) ;
224+
225+ const statusBarStyle = resolveSystemBarStyle ( props . statusBarStyle ) ;
226+ const navigationBarStyle = resolveSystemBarStyle ( props . navigationBarStyle ) ;
227+
228+ if ( typeof statusBarStyle === "string" ) {
229+ setStatusBarStyle ( statusBarStyle ) ;
230+ }
231+ if ( typeof navigationBarStyle === "string" ) {
232+ setNavigationBarStyle ( navigationBarStyle ) ;
233+ }
234+ }
235+
236+ /**
237+ * Show or hide the SystemBars
238+ *
239+ * @param hidden Hide the SystemBars.
240+ */
241+ function setHidden ( hidden : SystemBarsProps [ "hidden" ] ) {
242+ const { statusBarHidden, navigationBarHidden } = resolveProps ( { hidden } ) ;
243+
244+ if ( typeof statusBarHidden === "boolean" ) {
245+ setStatusBarHidden ( statusBarHidden ) ;
246+ }
247+ if ( typeof navigationBarHidden === "boolean" ) {
248+ setNavigationBarHidden ( navigationBarHidden ) ;
249+ }
250+ }
251+
252+ export function SystemBars ( props : SystemBarsProps ) {
253+ const {
254+ statusBarStyle,
255+ navigationBarStyle,
256+ statusBarHidden,
257+ navigationBarHidden,
258+ } = resolveProps ( props ) ;
206259
207260 const stableProps = useMemo < SystemBarsProps > (
208261 ( ) => ( {
@@ -252,3 +305,5 @@ export function SystemBars({ hidden, style }: SystemBarsProps) {
252305SystemBars . pushStackEntry = pushStackEntry ;
253306SystemBars . popStackEntry = popStackEntry ;
254307SystemBars . replaceStackEntry = replaceStackEntry ;
308+ SystemBars . setStyle = setStyle ;
309+ SystemBars . setHidden = setHidden ;
0 commit comments