Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v5 - Bye AndroidX, dark mode + brand image support, useHideAnimation hook, etc. #475

Merged
merged 56 commits into from
Aug 21, 2023

Conversation

zoontek
Copy link
Owner

@zoontek zoontek commented Aug 8, 2023

👋 Hi folks!

This PR has been opened to track the development of the next major version: v5 ✨
It's the result of several months of work (I'm working on it on my free time only) and includes a lot!

What's new

Bye AndroidX 👋

v4 introduced the usage of the official Android SplashScreen API with androidx.core:core-splashscreen in order to support Android 12+. But this change came with a lot of issues (#381, #418, #440, #456, etc.), and those issues seem to be ignored on the Google issue tracker. The next version now uses its own polyfill, compatible with Android 5+ (without any degraded mode, compared to the AndroidX one).

Dark mode 🌚

The generator is now able to output a lot more files, including dark mode versions of all the splash screen assets (in all required pixel densities, but also config files, etc.)
The update is simple: run the generator, drag and drop the newly created Colors.xcassets in your Xcode project, done!

Brand image support 🏢

Dropping AndroidX was also necessary to add brand images support on Android 5+ as the feature wasn't polyfilled (and android:windowSplashScreenBrandingImage is only available on Android 12+).
You can finally tell your boss that the company logo will be visible at app opening 🧑‍💼

An updated CLI 🧑‍💻

In order to support all these new features, I had to publish an updated CLI generator. By default, it will be as capable as the previous one (android, iOS and the assets directory). The only new emitted file is the manifest (for useHideAnimation usage). But in order to to use the --brand, --brand-width and --dark-* options, you must specify a --license-key 🔑

With it, the generator is able to output over 50 files (logo and brand images generated in all pixel densities, dark mode versions, etc.), saving you (and your company!) a massive amount of time not only at creation, but also at each adjustment.

Usage: react-native generate-bootsplash [options] <logo>

Generate a launch screen using a logo file path (PNG or SVG)

Options:
  --background <string>       Background color (in hexadecimal format) (default: "#fff")
  --logo-width <number>       Logo width at @1x (in dp - we recommend approximately ~100) (default: 100)
  --assets-output <string>    Assets output directory path
  --platforms <list>          Platforms to generate for, separated by a comma (default: "android,ios")
  --flavor <string>           Android flavor build variant (where your resource directory is) (default: "main")
  --license-key <string>      License key to enable brand and dark mode assets generation
  --brand <string>            Brand file path (PNG or SVG)
  --brand-width <number>      Brand width at @1x (in dp - we recommend approximately ~80) (default: 80)
  --dark-background <string>  [dark mode] Background color (in hexadecimal format)
  --dark-logo <string>        [dark mode] Logo file path (PNG or SVG)
  --dark-brand <string>       [dark mode] Brand file path (PNG or SVG)
  -h, --help                  display help for command

I know, free software is always better. But I think it's a good way to make the development of this library (and indirectly, react-native-permissions and react-native-localize) sustainable.
Monetizing open source is a hard task and I'm really glad a few individuals and companies are sponsoring my work, but unfortunately it's not systematic yet for companies to give a bit, even if their products are often built using free open source maintainers work.

❗️ Important: If you are currently sponsoring me, or sponsored me once in the past, contact me to get a free license key. It could have been any amount, even only 1$ for a coffee ☕️

👉 You can buy a license on Gumroad

useHideAnimation 🫣

You always wanted a custom hide animation, similar to the one in the example project? useHideAnimation is a new hook that will help you creating one, in the easiest way possible.

How does it work? First, run the generator with the --assets-output option. Once the files are ready, create a custom splash screen:

const AnimatedBootSplash = ({ onAnimationEnd }: { onAnimationEnd: () => void }) => {
  const [opacity] = useState(() => new Animated.Value(1));
  const [translateY] = useState(() => new Animated.Value(0));

  // note that you can also animate the brand image (check the documentation)
  const { container, logo } = BootSplash.useHideAnimation({

    // the manifest file is generated when --assets-output is specified
    // it includes colors and computed sizes values
    manifest: require("../assets/bootsplash_manifest.json"),

    // the required generated assets
    logo: require("../assets/bootsplash_logo.png"),
    darkLogo: require("../assets/bootsplash_dark_logo.png"),

    // specify if you are using translucent status / navigation bars
    // in order to avoid a shift between the native and JS splash screen
    statusBarTranslucent: true,
    navigationBarTranslucent: false,

    // run animations. the call to hide() will be done automatically
    // you can use Animated, but also react-native-reanimated, etc.
    animate: () => {
      const { height } = Dimensions.get("window");

      Animated.stagger(250, [
        Animated.spring(translateY, {
          toValue: -50,
          useNativeDriver: true,
        }),
        Animated.spring(translateY, {
          toValue: height,
          useNativeDriver: true,
        }),
      ]).start();

      Animated.timing(opacity, {
        toValue: 0,
        duration: 150,
        delay: 350,
        useNativeDriver: true,
      }).start(() => {
        onAnimationEnd();
      });
    },
  });

  return (
    <Animated.View {...container} style={[container.style, { opacity }]}>
      <Animated.Image
        {...logo}
        style={[logo.style, { transform: [{ translateY }] }]}
      />
    </Animated.View>
  );
};

Then uses it:

const App = () => {
  const [visible, setVisible] = useState(true);

  return (
    <View style={{ flex: 1 }}>
      {/* content */}

      {visible && (
        <AnimatedBootSplash
          onAnimationEnd={() => {
            setVisible(false);
          }}
        />
      )}
    </View>
  );
};
useHideAnimation.usage.mp4

Other changes

  • To avoid conflicts, Android provided theme / properties has been renamed Theme.BootSplash, bootSplashBackground, bootSplashLogo, bootSplashBrand and postBootSplashTheme.
  • Android generated assets has been migrated from mipmap-* directories to drawable-* ones.
  • The duration argument has been removed from fade() options.
  • The CLI now output a bootsplash_manifest.json file to share image sizes + colors with the JS thread (used by useHideAnimation).
  • getVisibilityStatus() has been replaced with isVisible() (which returns a Promise<boolean>). The transitioning does not exists anymore (when the splash screen is fading, it stays visible until complete disappearance).
  • --assets-path CLI option has been renamed --assets-output.
  • React native < 0.70 and iOS < 12.4 support has been dropped.
  • ReScript bindings has been removed as I don't know how to write them. Feels free to open a PR to add it back.

How to try it

  1. Install the @next version:
$ npm install --save react-native-bootsplash@next
# --- or ---
$ yarn add react-native-bootsplash@next
  1. Follow the updated MIGRATION.md
  2. Finally, if you meet some, report any issue here 🐛

What's next?

  • I'm planning to work on web support, would like it done before the stable v5 release 🌐
  • I started working on a new library to handle cover screens. A lot of folks here are asking for a show method and I personally think it's not a good idea, as calling the splash screen back is not really what we can call good UX.
    The goal of this library will be allowing you to design multiple covers screen (ex: for OTA update, for privacy when the app is in multi task), each ones with its own design.

@liamjones
Copy link

@MasonLe2497 No, you can only set a colour for the background in Android 12+, nothing more: https://developer.android.com/reference/android/R.attr#windowSplashScreenBackground

@zoontek
Copy link
Owner Author

zoontek commented Aug 14, 2023

@MasonLe2497 No, you can only use properties specified in the migration guide / v5 README. @liamjones is right, only color can be used as background on Android 12+.

@zoontek
Copy link
Owner Author

zoontek commented Aug 14, 2023

5.0.0-rc.0 is out with web support!

The generator will update your index.html file (or the file you specify using the new --html option) with both light and dark mode. The reason is simple: as light and dark mode assets are often nearly identical (same shape, different colors), GZIP will do a tremendous job on it:

Screenshot 2023-08-14 at 11 04 33

Of course, it supports all the features from iOS / Android versions (dark mode, brand image)

Screen.Recording.2023-08-14.at.12.26.47.mp4

@zoontek zoontek mentioned this pull request Aug 14, 2023
@sssajjad007
Copy link

hi,

Android generated assets has been migrated from mipmap-* directories to drawable-* ones.

No file was created inside drawable.
i use this command

 yarn react-native generate-bootsplash assets/images/bootsplash_logo_original.svg --background=F5FCFF --logo-width=100 --assets-output=assets --flavor=main --platforms=android,ios

@zoontek
Copy link
Owner Author

zoontek commented Aug 14, 2023

@sssajjad007 Update to latest v5 beta, don't forget to run npm install / yarn install.

@sssajjad007
Copy link

@sssajjad007 Update to latest v5 beta, don't forget to run npm install / yarn install.

Yes, I did the same, also ./gradlew clean

there is repo & output files :
https://github.com/sssajjad007/react-native-navigation-fabric-boilerApp/tree/main/assets

@zoontek
Copy link
Owner Author

zoontek commented Aug 14, 2023

@sssajjad007 I just cloned your project, ran the exact same command, it's correctly outputed files in android/app/src/main/res/drawable-*. You probably forgot to commit the files?

Screenshot 2023-08-14 at 22 41 44 Screenshot 2023-08-14 at 22 39 57

@sssajjad007
Copy link

sssajjad007 commented Aug 14, 2023

@zoontek
i use same command but asset was not created for Android and iOS

image

but i use command without --platform

image

and its work, i think the problem is with my terminal.
thanks, i appreciate

@zoontek
Copy link
Owner Author

zoontek commented Aug 14, 2023

@sssajjad007 100% normal, platforms items must be separated with a comma.

--platforms=ios,android -> the valus is ios,android ✅
--platforms=ios android -> the value is ios android ❌ (as you used a space)

Screenshot 2023-08-14 at 22 58 49

@nhutph
Copy link

nhutph commented Aug 18, 2023

you have plan to merge pr to prod bro ?

@zoontek
Copy link
Owner Author

zoontek commented Aug 18, 2023

@nhutph When stable version is released.

But you can fully access the v5 README, install the RC (react-native-bootsplash@next), no need to wait for a master merge to use it.

@nhutph
Copy link

nhutph commented Aug 18, 2023

Greate!!!

@zoontek zoontek merged commit f90c5c9 into master Aug 21, 2023
@zoontek zoontek deleted the v5 branch August 21, 2023 21:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants