diff --git a/packages/react-native/Libraries/Components/StatusBar/StatusBar.js b/packages/react-native/Libraries/Components/StatusBar/StatusBar.js index 2145d12fbf54..86e6e455fcab 100644 --- a/packages/react-native/Libraries/Components/StatusBar/StatusBar.js +++ b/packages/react-native/Libraries/Components/StatusBar/StatusBar.js @@ -529,15 +529,17 @@ class StatusBar extends React.Component { console.warn( `\`StatusBar._updatePropsStack\`: Color ${mergedProps.backgroundColor.value} parsed to null or undefined`, ); - } else { - invariant( - typeof processedColor === 'number', - 'Unexpected color given in StatusBar._updatePropsStack', - ); + } else if (typeof processedColor === 'number') { NativeStatusBarManagerAndroid.setColor( processedColor, mergedProps.backgroundColor.animated, ); + } else { + NativeStatusBarManagerAndroid.setColorObject( + // $FlowFixMe[incompatible-type] - Opaque NativeColorValue on Android matches the spec shape {resource_paths: Array}. + processedColor, + mergedProps.backgroundColor.animated, + ); } if (!oldProps || oldProps.hidden?.value !== mergedProps.hidden.value) { NativeStatusBarManagerAndroid.setHidden(mergedProps.hidden.value); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.kt index e4e67f1cc055..0630b3e2701e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.kt @@ -16,9 +16,11 @@ import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat import com.facebook.common.logging.FLog import com.facebook.fbreact.specs.NativeStatusBarManagerAndroidSpec +import com.facebook.react.bridge.ColorPropConverter import com.facebook.react.bridge.GuardedRunnable import com.facebook.react.bridge.NativeModule import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReadableMap import com.facebook.react.bridge.UiThreadUtil import com.facebook.react.common.ReactConstants import com.facebook.react.interfaces.ExtraWindowEventListener @@ -79,7 +81,24 @@ internal class StatusBarModule(reactContext: ReactApplicationContext?) : @Suppress("DEPRECATION") override fun setColor(colorDouble: Double, animated: Boolean) { - val color = colorDouble.toInt() + applyStatusBarColor(colorDouble.toInt(), animated) + } + + @Suppress("DEPRECATION") + override fun setColorObject(color: ReadableMap, animated: Boolean) { + val resolved = ColorPropConverter.getColor(color, reactApplicationContext) + if (resolved == null) { + FLog.w( + ReactConstants.TAG, + "StatusBarModule: Ignored status bar change, unable to resolve color.", + ) + return + } + applyStatusBarColor(resolved, animated) + } + + @Suppress("DEPRECATION") + private fun applyStatusBarColor(color: Int, animated: Boolean) { val activity = reactApplicationContext.getCurrentActivity() if (activity == null) { FLog.w( diff --git a/packages/react-native/src/private/specs_DEPRECATED/modules/NativeStatusBarManagerAndroid.js b/packages/react-native/src/private/specs_DEPRECATED/modules/NativeStatusBarManagerAndroid.js index 4ef517a7928b..a8962d83d775 100644 --- a/packages/react-native/src/private/specs_DEPRECATED/modules/NativeStatusBarManagerAndroid.js +++ b/packages/react-native/src/private/specs_DEPRECATED/modules/NativeStatusBarManagerAndroid.js @@ -12,12 +12,20 @@ import type {TurboModule} from '../../../../Libraries/TurboModule/RCTExport'; import * as TurboModuleRegistry from '../../../../Libraries/TurboModule/TurboModuleRegistry'; +export type NativePlatformColorValue = { + readonly resource_paths: Array, +}; + export interface Spec extends TurboModule { readonly getConstants: () => { readonly HEIGHT: number, readonly DEFAULT_BACKGROUND_COLOR: number, }; readonly setColor: (color: number, animated: boolean) => void; + readonly setColorObject: ( + color: NativePlatformColorValue, + animated: boolean, + ) => void; readonly setTranslucent: (translucent: boolean) => void; /** @@ -47,6 +55,10 @@ const NativeStatusBarManager = { NativeModule.setColor(color, animated); }, + setColorObject(color: NativePlatformColorValue, animated: boolean): void { + NativeModule.setColorObject(color, animated); + }, + setTranslucent(translucent: boolean): void { NativeModule.setTranslucent(translucent); }, diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api index cfe0cb56238c..5e955965261d 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api @@ -8615,6 +8615,12 @@ struct facebook::react::NativeSourceCodeSourceCodeConstants { public bool operator==(const facebook::react::NativeSourceCodeSourceCodeConstants& other) const; } +template +struct facebook::react::NativeStatusBarManagerAndroidNativePlatformColorValue { + public P0 resource_paths; + public bool operator==(const facebook::react::NativeStatusBarManagerAndroidNativePlatformColorValue& other) const; +} + template class facebook::react::SyncCallback { public R call(Args... args) const; @@ -9457,6 +9463,14 @@ struct facebook::react::NativeSourceCodeSourceCodeConstantsBridging { public static facebook::jsi::String scriptURLToJs(facebook::jsi::Runtime& rt, decltype(types.scriptURL) value); } +template +struct facebook::react::NativeStatusBarManagerAndroidNativePlatformColorValueBridging { + public static T fromJs(facebook::jsi::Runtime& rt, const facebook::jsi::Object& value, const std::shared_ptr& jsInvoker); + public static T types; + public static facebook::jsi::Array resource_pathsToJs(facebook::jsi::Runtime& rt, decltype(types.resource_paths) value); + public static facebook::jsi::Object toJs(facebook::jsi::Runtime& rt, const T& value, const std::shared_ptr& jsInvoker); +} + template struct facebook::react::RectangleCorners { public T bottomLeft; diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api index 3432343ed079..95b4a0ce78a9 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api @@ -8391,6 +8391,12 @@ struct facebook::react::NativeSourceCodeSourceCodeConstants { public bool operator==(const facebook::react::NativeSourceCodeSourceCodeConstants& other) const; } +template +struct facebook::react::NativeStatusBarManagerAndroidNativePlatformColorValue { + public P0 resource_paths; + public bool operator==(const facebook::react::NativeStatusBarManagerAndroidNativePlatformColorValue& other) const; +} + template class facebook::react::SyncCallback { public R call(Args... args) const; @@ -9095,6 +9101,13 @@ struct facebook::react::NativeSourceCodeSourceCodeConstantsBridging { public static facebook::jsi::Object toJs(facebook::jsi::Runtime& rt, const T& value, const std::shared_ptr& jsInvoker); } +template +struct facebook::react::NativeStatusBarManagerAndroidNativePlatformColorValueBridging { + public static T fromJs(facebook::jsi::Runtime& rt, const facebook::jsi::Object& value, const std::shared_ptr& jsInvoker); + public static T types; + public static facebook::jsi::Object toJs(facebook::jsi::Runtime& rt, const T& value, const std::shared_ptr& jsInvoker); +} + template struct facebook::react::RectangleCorners { public T bottomLeft; diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api index d46afaf86d4b..402ca2c79b4f 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api @@ -8606,6 +8606,12 @@ struct facebook::react::NativeSourceCodeSourceCodeConstants { public bool operator==(const facebook::react::NativeSourceCodeSourceCodeConstants& other) const; } +template +struct facebook::react::NativeStatusBarManagerAndroidNativePlatformColorValue { + public P0 resource_paths; + public bool operator==(const facebook::react::NativeStatusBarManagerAndroidNativePlatformColorValue& other) const; +} + template class facebook::react::SyncCallback { public R call(Args... args) const; @@ -9310,6 +9316,13 @@ struct facebook::react::NativeSourceCodeSourceCodeConstantsBridging { public static facebook::jsi::Object toJs(facebook::jsi::Runtime& rt, const T& value, const std::shared_ptr& jsInvoker); } +template +struct facebook::react::NativeStatusBarManagerAndroidNativePlatformColorValueBridging { + public static T fromJs(facebook::jsi::Runtime& rt, const facebook::jsi::Object& value, const std::shared_ptr& jsInvoker); + public static T types; + public static facebook::jsi::Object toJs(facebook::jsi::Runtime& rt, const T& value, const std::shared_ptr& jsInvoker); +} + template struct facebook::react::RectangleCorners { public T bottomLeft;