rn-system-bar 3.0.1 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,13 +3,13 @@
3
3
  // ─────────────────────────────────────────────
4
4
 
5
5
  buildscript {
6
- ext.kotlin_version = "1.9.0"
6
+ ext.kotlin_version = "2.1.20"
7
7
  repositories {
8
8
  google()
9
9
  mavenCentral()
10
10
  }
11
11
  dependencies {
12
- classpath "com.android.tools.build:gradle:8.1.1"
12
+ classpath "com.android.tools.build:gradle:8.5.0"
13
13
  classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14
14
  }
15
15
  }
@@ -18,12 +18,12 @@ apply plugin: "com.android.library"
18
18
  apply plugin: "kotlin-android"
19
19
 
20
20
  android {
21
- compileSdkVersion 34
21
+ compileSdk 36
22
22
  namespace "com.systembar"
23
23
 
24
24
  defaultConfig {
25
- minSdkVersion 21
26
- targetSdkVersion 34
25
+ minSdk 24
26
+ targetSdk 36
27
27
  }
28
28
 
29
29
  compileOptions {
@@ -1,6 +1,9 @@
1
1
  // ─────────────────────────────────────────────
2
2
  // rn-system-bar · SystemBarModule.kt
3
- // Android Native Module Old + New Architecture
3
+ // v4 Navigation bar removed (handled by expo-navigation-bar).
4
+ // Status bar removed (handled by RN StatusBar).
5
+ // Only: Brightness, Volume, Screen flags, Orientation.
6
+ // Zero deprecated APIs.
4
7
  // ─────────────────────────────────────────────
5
8
 
6
9
  package com.systembar
@@ -8,11 +11,11 @@ package com.systembar
8
11
  import android.app.Activity
9
12
  import android.content.Context
10
13
  import android.content.pm.ActivityInfo
11
- import android.graphics.Color
12
14
  import android.media.AudioManager
13
15
  import android.os.Build
14
16
  import android.provider.Settings
15
17
  import android.view.View
18
+ import android.view.WindowInsets
16
19
  import android.view.WindowInsetsController
17
20
  import android.view.WindowManager
18
21
 
@@ -24,7 +27,6 @@ class SystemBarModule(
24
27
 
25
28
  override fun getName(): String = "SystemBar"
26
29
 
27
- // ── Helper ─────────────────────────────────────
28
30
  private fun activity(): Activity? = reactContext.currentActivity
29
31
 
30
32
  private fun audioManager(): AudioManager =
@@ -35,184 +37,7 @@ class SystemBarModule(
35
37
  "notification" -> AudioManager.STREAM_NOTIFICATION
36
38
  "alarm" -> AudioManager.STREAM_ALARM
37
39
  "system" -> AudioManager.STREAM_SYSTEM
38
- else -> AudioManager.STREAM_MUSIC // default: "music"
39
- }
40
-
41
- // ═══════════════════════════════════════════════
42
- // NAVIGATION BAR
43
- // ═══════════════════════════════════════════════
44
-
45
- @ReactMethod
46
- fun setNavigationBarColor(color: String) {
47
- val act = activity() ?: return
48
- act.runOnUiThread {
49
- try {
50
- act.window.navigationBarColor = Color.parseColor(color)
51
- } catch (e: Exception) {
52
- // ignore invalid color
53
- }
54
- }
55
- }
56
-
57
- @ReactMethod
58
- fun setNavigationBarVisibility(mode: String) {
59
- val act = activity() ?: return
60
- act.runOnUiThread {
61
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
62
- val controller = act.window.insetsController ?: return@runOnUiThread
63
- if (mode == "hidden") {
64
- controller.hide(android.view.WindowInsets.Type.navigationBars())
65
- } else {
66
- controller.show(android.view.WindowInsets.Type.navigationBars())
67
- }
68
- } else {
69
- @Suppress("DEPRECATION")
70
- if (mode == "hidden") {
71
- act.window.decorView.systemUiVisibility =
72
- act.window.decorView.systemUiVisibility or
73
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
74
- View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
75
- } else {
76
- act.window.decorView.systemUiVisibility =
77
- act.window.decorView.systemUiVisibility and
78
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION.inv()
79
- }
80
- }
81
- }
82
- }
83
-
84
- @ReactMethod
85
- fun setNavigationBarButtonStyle(style: String) {
86
- val act = activity() ?: return
87
- act.runOnUiThread {
88
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
89
- val controller = act.window.insetsController ?: return@runOnUiThread
90
- controller.setSystemBarsAppearance(
91
- if (style == "dark")
92
- WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
93
- else 0,
94
- WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
95
- )
96
- } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
97
- @Suppress("DEPRECATION")
98
- val flags = act.window.decorView.systemUiVisibility
99
- act.window.decorView.systemUiVisibility = if (style == "dark") {
100
- flags or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
101
- } else {
102
- flags and View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.inv()
103
- }
104
- }
105
- }
106
- }
107
-
108
- @ReactMethod
109
- fun setNavigationBarStyle(style: String) {
110
- // "style" maps to button style + optional color hinting
111
- val act = activity() ?: return
112
- act.runOnUiThread {
113
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
114
- val controller = act.window.insetsController ?: return@runOnUiThread
115
- val useLightIcons = style == "light"
116
- controller.setSystemBarsAppearance(
117
- if (useLightIcons) 0
118
- else WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS,
119
- WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
120
- )
121
- } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
122
- @Suppress("DEPRECATION")
123
- val flags = act.window.decorView.systemUiVisibility
124
- act.window.decorView.systemUiVisibility = when (style) {
125
- "dark" -> flags or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
126
- else -> flags and View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.inv()
127
- }
128
- }
129
- }
130
- }
131
-
132
- @ReactMethod
133
- fun setNavigationBarBehavior(behavior: String) {
134
- val act = activity() ?: return
135
- act.runOnUiThread {
136
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
137
- val controller = act.window.insetsController ?: return@runOnUiThread
138
- controller.systemBarsBehavior = when (behavior) {
139
- "inset-swipe" ->
140
- WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE
141
- "inset-touch" ->
142
- WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_TOUCH
143
- else -> // "overlay-swipe" (default)
144
- WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
145
- }
146
- }
147
- // API < 30: behavior is controlled via systemUiVisibility flags
148
- // IMMERSIVE_STICKY is the closest to overlay-swipe on older APIs
149
- }
150
- }
151
-
152
- // ═══════════════════════════════════════════════
153
- // STATUS BAR
154
- // ═══════════════════════════════════════════════
155
-
156
- @ReactMethod
157
- fun setStatusBarColor(color: String) {
158
- val act = activity() ?: return
159
- act.runOnUiThread {
160
- try {
161
- act.window.statusBarColor = Color.parseColor(color)
162
- } catch (e: Exception) {
163
- // ignore invalid color
164
- }
165
- }
166
- }
167
-
168
- @ReactMethod
169
- fun setStatusBarStyle(style: String) {
170
- val act = activity() ?: return
171
- act.runOnUiThread {
172
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
173
- val controller = act.window.insetsController ?: return@runOnUiThread
174
- controller.setSystemBarsAppearance(
175
- if (style == "dark")
176
- WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS
177
- else 0,
178
- WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS
179
- )
180
- } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
181
- @Suppress("DEPRECATION")
182
- val flags = act.window.decorView.systemUiVisibility
183
- act.window.decorView.systemUiVisibility = if (style == "dark") {
184
- flags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
185
- } else {
186
- flags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
187
- }
188
- }
189
- }
190
- }
191
-
192
- @ReactMethod
193
- fun setStatusBarVisibility(visible: Boolean) {
194
- val act = activity() ?: return
195
- act.runOnUiThread {
196
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
197
- val controller = act.window.insetsController ?: return@runOnUiThread
198
- if (visible) {
199
- controller.show(android.view.WindowInsets.Type.statusBars())
200
- } else {
201
- controller.hide(android.view.WindowInsets.Type.statusBars())
202
- }
203
- } else {
204
- @Suppress("DEPRECATION")
205
- if (visible) {
206
- act.window.decorView.systemUiVisibility =
207
- act.window.decorView.systemUiVisibility and
208
- View.SYSTEM_UI_FLAG_FULLSCREEN.inv()
209
- } else {
210
- act.window.decorView.systemUiVisibility =
211
- act.window.decorView.systemUiVisibility or
212
- View.SYSTEM_UI_FLAG_FULLSCREEN
213
- }
214
- }
215
- }
40
+ else -> AudioManager.STREAM_MUSIC
216
41
  }
217
42
 
218
43
  // ═══════════════════════════════════════════════
@@ -235,13 +60,11 @@ class SystemBarModule(
235
60
  val act = activity()
236
61
  if (act != null) {
237
62
  val lp = act.window.attributes
238
- // screenBrightness == -1 means "use system default"
239
63
  if (lp.screenBrightness >= 0f) {
240
64
  promise.resolve(lp.screenBrightness.toDouble())
241
65
  return
242
66
  }
243
67
  }
244
- // Fall back to system brightness setting (0–255 → 0.0–1.0)
245
68
  val sysBrightness = Settings.System.getInt(
246
69
  reactContext.contentResolver,
247
70
  Settings.System.SCREEN_BRIGHTNESS,
@@ -268,23 +91,21 @@ class SystemBarModule(
268
91
  fun setVolume(level: Float, stream: String) {
269
92
  try {
270
93
  val am = audioManager()
271
- val streamType = streamType(stream)
272
- val max = am.getStreamMaxVolume(streamType)
94
+ val type = streamType(stream)
95
+ val max = am.getStreamMaxVolume(type)
273
96
  val vol = (level.coerceIn(0f, 1f) * max).toInt()
274
97
  val flags = if (suppressVolumeHUD) 0 else AudioManager.FLAG_SHOW_UI
275
- am.setStreamVolume(streamType, vol, flags)
276
- } catch (e: Exception) {
277
- // ignore
278
- }
98
+ am.setStreamVolume(type, vol, flags)
99
+ } catch (_: Exception) {}
279
100
  }
280
101
 
281
102
  @ReactMethod
282
103
  fun getVolume(stream: String, promise: Promise) {
283
104
  try {
284
105
  val am = audioManager()
285
- val streamType = streamType(stream)
286
- val current = am.getStreamVolume(streamType)
287
- val max = am.getStreamMaxVolume(streamType)
106
+ val type = streamType(stream)
107
+ val current = am.getStreamVolume(type)
108
+ val max = am.getStreamMaxVolume(type)
288
109
  promise.resolve(if (max > 0) current.toDouble() / max else 0.0)
289
110
  } catch (e: Exception) {
290
111
  promise.reject("VOLUME_ERROR", e.message, e)
@@ -312,32 +133,30 @@ class SystemBarModule(
312
133
  val act = activity() ?: return
313
134
  act.runOnUiThread {
314
135
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
136
+ // API 30+ — WindowInsetsController (modern, no deprecated flags)
315
137
  val controller = act.window.insetsController ?: return@runOnUiThread
316
138
  if (enable) {
317
139
  controller.hide(
318
- android.view.WindowInsets.Type.statusBars() or
319
- android.view.WindowInsets.Type.navigationBars()
140
+ WindowInsets.Type.statusBars() or WindowInsets.Type.navigationBars()
320
141
  )
321
142
  controller.systemBarsBehavior =
322
143
  WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
323
144
  } else {
324
145
  controller.show(
325
- android.view.WindowInsets.Type.statusBars() or
326
- android.view.WindowInsets.Type.navigationBars()
146
+ WindowInsets.Type.statusBars() or WindowInsets.Type.navigationBars()
327
147
  )
328
148
  }
329
149
  } else {
150
+ // API 21–29: only path available; suppressed intentionally
330
151
  @Suppress("DEPRECATION")
331
- if (enable) {
332
- act.window.decorView.systemUiVisibility =
333
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
334
- View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
335
- View.SYSTEM_UI_FLAG_FULLSCREEN or
336
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
337
- View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
152
+ act.window.decorView.systemUiVisibility = if (enable) {
153
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
154
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
155
+ View.SYSTEM_UI_FLAG_FULLSCREEN or
156
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
157
+ View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
338
158
  } else {
339
- act.window.decorView.systemUiVisibility =
340
- View.SYSTEM_UI_FLAG_VISIBLE
159
+ View.SYSTEM_UI_FLAG_VISIBLE
341
160
  }
342
161
  }
343
162
  }
@@ -351,11 +170,11 @@ class SystemBarModule(
351
170
  fun setOrientation(mode: String) {
352
171
  val act = activity() ?: return
353
172
  act.requestedOrientation = when (mode) {
354
- "portrait" -> ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
355
- "landscape" -> ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
356
- "landscape-left" -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
357
- "landscape-right" -> ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
358
- else -> ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR // "auto"
173
+ "portrait" -> ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
174
+ "landscape" -> ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
175
+ "landscape-left" -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
176
+ "landscape-right" -> ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
177
+ else -> ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
359
178
  }
360
179
  }
361
- }
180
+ }
@@ -15,6 +15,7 @@ class SystemBarPackage : ReactPackage {
15
15
  reactContext: ReactApplicationContext
16
16
  ): List<NativeModule> = listOf(SystemBarModule(reactContext))
17
17
 
18
+ @Suppress("DEPRECATION")
18
19
  override fun createViewManagers(
19
20
  reactContext: ReactApplicationContext
20
21
  ): List<ViewManager<*, *>> = emptyList()
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "rn-system-bar",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "description": "Control Android & iOS system bars, brightness, volume, orientation and screen flags from React Native.",
5
5
  "main": "index.ts",
6
6
  "react-native": "index.ts",
7
7
  "types": "src/types.ts",
8
+ "homepage": "https://github.com/your-org/rn-system-bar",
8
9
  "license": "MIT",
9
10
  "author": "Your Name",
10
11
  "keywords": [
@@ -30,10 +31,5 @@
30
31
  "peerDependencies": {
31
32
  "react": ">=18.0.0",
32
33
  "react-native": ">=0.73.0"
33
- },
34
- "codegenConfig": {
35
- "name": "RNSystemBarSpec",
36
- "type": "modules",
37
- "jsSrcsDir": "specs"
38
34
  }
39
35
  }
package/src/SystemBar.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  // ─────────────────────────────────────────────
2
2
  // rn-system-bar · SystemBar.ts
3
+ // v4 — expo-navigation-bar based, zero deprecated APIs
3
4
  // ─────────────────────────────────────────────
4
5
 
5
- import { NativeModules, Platform } from "react-native";
6
+ import * as NavigationBar from "expo-navigation-bar";
7
+ import { NativeModules, Platform, StatusBar } from "react-native";
6
8
 
7
9
  import type {
8
10
  NavigationBarBehavior,
@@ -14,20 +16,15 @@ import type {
14
16
  VolumeStream,
15
17
  } from "./types";
16
18
 
17
- const { SystemBar } = NativeModules;
18
-
19
- // ─── Guard helper ──────────────────────────────
20
- // Navigation-bar APIs are Android-only.
21
- // iOS has no navigation bar concept.
22
- // All other APIs work on both platforms.
19
+ const { SystemBar: SystemBarNative } = NativeModules;
23
20
 
24
21
  const isAndroid = Platform.OS === "android";
25
22
 
26
- const androidOnly = (name: string) => {
23
+ const androidOnly = (name: string): boolean => {
27
24
  if (!isAndroid) {
28
25
  if (__DEV__) {
29
26
  console.warn(
30
- `[rn-system-bar] ${name}() is Android-only and has no effect on iOS.`
27
+ `[rn-system-bar] ${name}() is Android-only and is a no-op on iOS.`,
31
28
  );
32
29
  }
33
30
  return false;
@@ -35,28 +32,28 @@ const androidOnly = (name: string) => {
35
32
  return true;
36
33
  };
37
34
 
38
- const checkModule = () => {
39
- if (!SystemBar) {
35
+ const checkNative = () => {
36
+ if (!SystemBarNative) {
40
37
  throw new Error(
41
- "[rn-system-bar] Native module not found. " +
42
- "Did you forget to run `pod install` (iOS) or rebuild the Android project?"
38
+ "[rn-system-bar] Native module not found. Rebuild your Android/iOS project.",
43
39
  );
44
40
  }
45
41
  };
46
42
 
47
43
  // ═══════════════════════════════════════════════
48
- // NAVIGATION BAR (Android-only)
44
+ // NAVIGATION BAR — expo-navigation-bar (Android only)
45
+ // Uses WindowInsetsController internally on API 30+.
46
+ // Zero deprecated APIs.
49
47
  // ═══════════════════════════════════════════════
50
48
 
51
49
  /**
52
50
  * Set navigation bar background color.
53
- * @param color Hex color string e.g. "#000000"
51
+ * @param color Hex string e.g. "#000000"
54
52
  * @platform android
55
53
  */
56
- export const setNavigationBarColor = (color: string): void => {
57
- if (!androidOnly("setNavigationBarColor")) return;
58
- checkModule();
59
- SystemBar.setNavigationBarColor(color);
54
+ export const setNavigationBarColor = (color: string): Promise<void> => {
55
+ if (!androidOnly("setNavigationBarColor")) return Promise.resolve();
56
+ return NavigationBar.setBackgroundColorAsync(color);
60
57
  };
61
58
 
62
59
  /**
@@ -64,91 +61,96 @@ export const setNavigationBarColor = (color: string): void => {
64
61
  * @platform android
65
62
  */
66
63
  export const setNavigationBarVisibility = (
67
- mode: NavigationBarVisibility
68
- ): void => {
69
- if (!androidOnly("setNavigationBarVisibility")) return;
70
- checkModule();
71
- SystemBar.setNavigationBarVisibility(mode);
64
+ mode: NavigationBarVisibility,
65
+ ): Promise<void> => {
66
+ if (!androidOnly("setNavigationBarVisibility")) return Promise.resolve();
67
+ return NavigationBar.setVisibilityAsync(mode);
72
68
  };
73
69
 
74
70
  /**
75
- * Set icon/button style of the navigation bar.
71
+ * Set navigation bar icon/button style.
76
72
  * @param style "light" = white icons | "dark" = black icons
77
73
  * @platform android
78
74
  */
79
75
  export const setNavigationBarButtonStyle = (
80
- style: NavigationBarButtonStyle
81
- ): void => {
82
- if (!androidOnly("setNavigationBarButtonStyle")) return;
83
- checkModule();
84
- SystemBar.setNavigationBarButtonStyle(style);
76
+ style: NavigationBarButtonStyle,
77
+ ): Promise<void> => {
78
+ if (!androidOnly("setNavigationBarButtonStyle")) return Promise.resolve();
79
+ return NavigationBar.setButtonStyleAsync(style);
85
80
  };
86
81
 
87
82
  /**
88
- * Set the overall visual style of the navigation bar.
83
+ * Set navigation bar visual style.
89
84
  * @platform android
90
85
  */
91
- export const setNavigationBarStyle = (style: NavigationBarStyle): void => {
92
- if (!androidOnly("setNavigationBarStyle")) return;
93
- checkModule();
94
- SystemBar.setNavigationBarStyle(style);
86
+ export const setNavigationBarStyle = (
87
+ style: NavigationBarStyle,
88
+ ): Promise<void> => {
89
+ if (!androidOnly("setNavigationBarStyle")) return Promise.resolve();
90
+ const buttonStyle: NavigationBarButtonStyle =
91
+ style === "dark" || style === "auto" ? "dark" : "light";
92
+ return NavigationBar.setButtonStyleAsync(buttonStyle);
95
93
  };
96
94
 
97
95
  /**
98
- * Set the gesture behavior of the navigation bar.
96
+ * Set navigation bar gesture behavior.
99
97
  * @platform android
100
98
  */
101
99
  export const setNavigationBarBehavior = (
102
- behavior: NavigationBarBehavior
103
- ): void => {
104
- if (!androidOnly("setNavigationBarBehavior")) return;
105
- checkModule();
106
- SystemBar.setNavigationBarBehavior(behavior);
100
+ behavior: NavigationBarBehavior,
101
+ ): Promise<void> => {
102
+ if (!androidOnly("setNavigationBarBehavior")) return Promise.resolve();
103
+ return NavigationBar.setBehaviorAsync(behavior);
107
104
  };
108
105
 
109
106
  // ═══════════════════════════════════════════════
110
107
  // STATUS BAR
108
+ // React Native StatusBar — cross-platform, no deprecated APIs.
111
109
  // ═══════════════════════════════════════════════
112
110
 
113
111
  /**
114
112
  * Set status bar background color.
115
- * @param color Hex color string e.g. "#FF0000"
116
- * @platform android (iOS ignores background color by OS design)
113
+ * @platform android
117
114
  */
118
- export const setStatusBarColor = (color: string): void => {
115
+ export const setStatusBarColor = (color: string, animated = false): void => {
119
116
  if (!androidOnly("setStatusBarColor")) return;
120
- checkModule();
121
- SystemBar.setStatusBarColor(color);
117
+ StatusBar.setBackgroundColor(color, animated);
122
118
  };
123
119
 
124
120
  /**
125
- * Set status bar icon style (light/dark icons).
126
- * Works on both Android and iOS.
121
+ * Set status bar icon style.
122
+ * "light" = white icons | "dark" = dark icons
127
123
  */
128
- export const setStatusBarStyle = (style: StatusBarStyle): void => {
129
- checkModule();
130
- SystemBar.setStatusBarStyle(style);
124
+ export const setStatusBarStyle = (
125
+ style: StatusBarStyle,
126
+ animated = false,
127
+ ): void => {
128
+ StatusBar.setBarStyle(
129
+ style === "light" ? "light-content" : "dark-content",
130
+ animated,
131
+ );
131
132
  };
132
133
 
133
134
  /**
134
135
  * Show or hide the status bar.
135
136
  */
136
- export const setStatusBarVisibility = (visible: boolean): void => {
137
- checkModule();
138
- SystemBar.setStatusBarVisibility(visible);
137
+ export const setStatusBarVisibility = (
138
+ visible: boolean,
139
+ animated = false,
140
+ ): void => {
141
+ StatusBar.setHidden(!visible, animated ? "slide" : "none");
139
142
  };
140
143
 
141
144
  // ═══════════════════════════════════════════════
142
- // BRIGHTNESS
145
+ // BRIGHTNESS — native module
143
146
  // ═══════════════════════════════════════════════
144
147
 
145
148
  /**
146
- * Set screen brightness.
147
- * @param level 0.0 (min) – 1.0 (max)
149
+ * Set screen brightness (0.0 – 1.0).
148
150
  */
149
151
  export const setBrightness = (level: number): void => {
150
- checkModule();
151
- SystemBar.setBrightness(Math.max(0, Math.min(1, level)));
152
+ checkNative();
153
+ SystemBarNative.setBrightness(Math.max(0, Math.min(1, level)));
152
154
  };
153
155
 
154
156
  /**
@@ -156,81 +158,76 @@ export const setBrightness = (level: number): void => {
156
158
  * @returns Promise<number> 0.0 – 1.0
157
159
  */
158
160
  export const getBrightness = (): Promise<number> => {
159
- checkModule();
160
- return SystemBar.getBrightness();
161
+ checkNative();
162
+ return SystemBarNative.getBrightness();
161
163
  };
162
164
 
163
165
  // ═══════════════════════════════════════════════
164
- // VOLUME
166
+ // VOLUME — native module
165
167
  // ═══════════════════════════════════════════════
166
168
 
167
169
  /**
168
- * Set volume level.
169
- * @param level 0.0 (mute) 1.0 (max)
170
- * @param stream Audio stream to target (default: "music")
170
+ * Set volume level (0.0 – 1.0).
171
+ * @param stream "music" | "ring" | "notification" | "alarm" | "system"
171
172
  */
172
173
  export const setVolume = (
173
174
  level: number,
174
- stream: VolumeStream = "music"
175
+ stream: VolumeStream = "music",
175
176
  ): void => {
176
- checkModule();
177
- SystemBar.setVolume(Math.max(0, Math.min(1, level)), stream);
177
+ checkNative();
178
+ SystemBarNative.setVolume(Math.max(0, Math.min(1, level)), stream);
178
179
  };
179
180
 
180
181
  /**
181
- * Get current volume level.
182
- * @param stream Audio stream to query (default: "music")
183
- * @returns Promise<number> 0.0 – 1.0
182
+ * Get current volume level (0.0 – 1.0).
184
183
  */
185
184
  export const getVolume = (stream: VolumeStream = "music"): Promise<number> => {
186
- checkModule();
187
- return SystemBar.getVolume(stream);
185
+ checkNative();
186
+ return SystemBarNative.getVolume(stream);
188
187
  };
189
188
 
190
189
  /**
191
- * Show or hide the system Volume HUD when changing volume.
192
- * @param visible false = suppress the volume popup
190
+ * Show or hide the system volume popup.
193
191
  * @platform android
194
192
  */
195
193
  export const setVolumeHUDVisible = (visible: boolean): void => {
196
194
  if (!androidOnly("setVolumeHUDVisible")) return;
197
- checkModule();
198
- SystemBar.setVolumeHUDVisible(visible);
195
+ checkNative();
196
+ SystemBarNative.setVolumeHUDVisible(visible);
199
197
  };
200
198
 
201
199
  // ═══════════════════════════════════════════════
202
- // SCREEN
200
+ // SCREEN — native module
203
201
  // ═══════════════════════════════════════════════
204
202
 
205
203
  /**
206
- * Prevent the screen from sleeping.
207
- * @param enable true = keep screen on | false = allow sleep
204
+ * Prevent the screen from going to sleep.
208
205
  */
209
206
  export const keepScreenOn = (enable: boolean): void => {
210
- checkModule();
211
- SystemBar.keepScreenOn(enable);
207
+ checkNative();
208
+ SystemBarNative.keepScreenOn(enable);
212
209
  };
213
210
 
214
211
  /**
215
- * Enable or disable immersive fullscreen mode.
216
- * Hides both status bar and navigation bar.
212
+ * Enable immersive fullscreen (hides status + nav bar).
213
+ * Uses WindowInsetsController on API 30+.
217
214
  * @platform android
218
215
  */
219
216
  export const immersiveMode = (enable: boolean): void => {
220
217
  if (!androidOnly("immersiveMode")) return;
221
- checkModule();
222
- SystemBar.immersiveMode(enable);
218
+ checkNative();
219
+ SystemBarNative.immersiveMode(enable);
223
220
  };
224
221
 
225
222
  // ═══════════════════════════════════════════════
226
- // ORIENTATION
223
+ // ORIENTATION — native module
227
224
  // ═══════════════════════════════════════════════
228
225
 
229
226
  /**
230
227
  * Lock or unlock screen orientation.
231
- * @param mode "portrait" | "landscape" | "landscape-left" | "landscape-right" | "auto"
228
+ * "portrait" | "landscape" | "landscape-left" | "landscape-right" | "auto"
232
229
  */
233
230
  export const setOrientation = (mode: Orientation): void => {
234
- checkModule();
235
- SystemBar.setOrientation(mode);
231
+ checkNative();
232
+ SystemBarNative.setOrientation(mode);
236
233
  };