zoontek / react-native-bootsplash

🚀 Show a splash screen during app startup. Hide it when you are ready.
MIT License
3.74k stars 258 forks source link

fix(android): BootTheme styles are overwritten instead of merged during Expo prebuild #650

Closed wise-danya closed 2 weeks ago

wise-danya commented 2 weeks ago

Before submitting a new issue

Bug summary

When using react-native-bootsplash with Expo config plugins, any custom styles added to BootTheme in styles.xml are completely removed during expo prebuild --clean. The only workaround is to place custom style plugins before react-native-bootsplash in the plugins array, which isn't intuitive and could lead to other issues.

Expected Behavior

The plugin should merge existing BootTheme styles with its required configurations rather than overwriting them completely. Custom style items that don't conflict with required bootsplash items should be preserved.

Library version

Environment info

System:
  OS: macOS 14.6.1
  CPU: (10) arm64 Apple M1 Max
  Memory: 142.67 MB / 32.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 20.18.0
    path: /opt/homebrew/opt/node@20/bin/node
  Yarn: Not Found
  npm:
    version: 10.8.2
    path: /opt/homebrew/opt/node@20/bin/npm
  Watchman:
    version: 2024.10.28.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.15.2
    path: /usr/local/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 23.4
      - iOS 17.4
      - macOS 14.4
      - tvOS 17.4
      - visionOS 1.1
      - watchOS 10.4
  Android SDK:
    Android NDK: 21.4.7075529
IDEs:
  Android Studio: 2021.3 AI-213.7172.25.2113.9123335
  Xcode:
    version: 15.3/15E204a
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.13
    path: /usr/bin/javac
  Ruby:
    version: 2.6.10
    path: /usr/bin/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.2.0
    wanted: 18.2.0
  react-native:
    installed: 0.74.5
    wanted: 0.74.5
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: true
  newArchEnabled: false

Steps to reproduce

  1. Set up an Expo project with react-native-bootsplash
  2. Add custom styles to BootTheme (e.g., status bar and navigation bar colors)
  3. Run expo prebuild --clean
  4. Observe that custom styles are removed from styles.xml

Reproducible sample code

Initial styles.xml:

<style name="BootTheme" parent="Theme.BootSplash">
  <item name="postBootSplashTheme">@style/AppTheme</item>
  <item name="bootSplashBackground">@color/bootsplash_background</item>
  <item name="bootSplashLogo">@drawable/bootsplash_logo</item>
  <item name="android:statusBarColor">@color/bootsplash_background</item>
  <item name="android:navigationBarColor">@color/bootsplash_background</item>
</style>

After expo prebuild --clean:

<style name="BootTheme" parent="Theme.BootSplash">
  <item name="postBootSplashTheme">@style/AppTheme</item>
  <item name="bootSplashBackground">@color/bootsplash_background</item>
  <item name="bootSplashLogo">@drawable/bootsplash_logo</item>
</style>

Technical Details

The issue is in withAndroidStyles plugin implementation where it filters out the existing BootTheme completely and creates a new one with only the required items:

const withBootTheme = [
  ...style.filter(({ $ }) => $.name !== "BootTheme"),
  {
    $: {
      name: "BootTheme",
      parent: /* ... */,
    },
    item,
  },
];

Proposed Solution

Modify the plugin to:

  1. Preserve existing BootTheme items that don't conflict with required items
  2. Merge them with required bootsplash configurations
  3. Maintain the plugin's core functionality while allowing customization

I'm happy to submit a PR with these changes if desired. Thank you!

zoontek commented 2 weeks ago

@wise-danya This is the intended behavior. The only extras customizations allowed on BootTheme are:

Transparent status bar

"plugins": [
  ["react-native-bootsplash", { "android": { "parentTheme": "TransparentStatus" } }]
]

Transparent status and navigation bars (what you are trying to do)

"plugins": [
  ["react-native-bootsplash", { "android": { "parentTheme": "EdgeToEdge" } }]
]

Setting the system bars colors

"plugins": [
  ["react-native-bootsplash", { "android": { "darkContentBarsStyle": true } }]
]

Everything is in the README.

wise-danya commented 2 weeks ago

@zoontek Thank you for the clarification! Now I see what happened - there was a typo in my app.json.

That's why I had to manually add status/navigation bar colors to get transparent bars during app launch. After fixing the configuration structure, everything works as documented. Sorry for the confusion!