1import {
2  AndroidConfig,
3  ConfigPlugin,
4  withAndroidColors,
5  withAndroidColorsNight,
6  withAndroidStyles,
7} from '@expo/config-plugins';
8import { Colors } from '@expo/config-plugins/build/android';
9import { ExpoConfig } from '@expo/config-types';
10
11import { getAndroidDarkSplashConfig, getAndroidSplashConfig } from './getAndroidSplashConfig';
12
13const styleResourceGroup = {
14  name: 'Theme.App.SplashScreen',
15  parent: 'AppTheme',
16};
17
18const SPLASH_COLOR_NAME = 'splashscreen_background';
19
20export const withAndroidSplashStyles: ConfigPlugin = (config) => {
21  config = withAndroidColors(config, (config) => {
22    const backgroundColor = getSplashBackgroundColor(config);
23    config.modResults = setSplashColorsForTheme(config.modResults, backgroundColor);
24    return config;
25  });
26  config = withAndroidColorsNight(config, (config) => {
27    const backgroundColor = getSplashDarkBackgroundColor(config);
28    config.modResults = setSplashColorsForTheme(config.modResults, backgroundColor);
29    return config;
30  });
31  config = withAndroidStyles(config, (config) => {
32    config.modResults = removeOldSplashStyleGroup(config.modResults);
33    config.modResults = setSplashStylesForTheme(config.modResults);
34    return config;
35  });
36  return config;
37};
38
39// Remove the old style group which didn't extend the base theme properly.
40export function removeOldSplashStyleGroup(styles: AndroidConfig.Resources.ResourceXML) {
41  const group = {
42    name: 'Theme.App.SplashScreen',
43    parent: 'Theme.AppCompat.Light.NoActionBar',
44  };
45
46  styles.resources.style = styles.resources.style?.filter?.(({ $: head }) => {
47    let matches = head.name === group.name;
48    if (group.parent != null && matches) {
49      matches = head.parent === group.parent;
50    }
51    return !matches;
52  });
53
54  return styles;
55}
56
57export function getSplashBackgroundColor(config: ExpoConfig): string | null {
58  return getAndroidSplashConfig(config)?.backgroundColor ?? null;
59}
60
61export function getSplashDarkBackgroundColor(config: ExpoConfig): string | null {
62  return getAndroidDarkSplashConfig(config)?.backgroundColor ?? null;
63}
64
65export function setSplashStylesForTheme(styles: AndroidConfig.Resources.ResourceXML) {
66  // Add splash screen image
67  return AndroidConfig.Styles.assignStylesValue(styles, {
68    add: true,
69    value: '@drawable/splashscreen',
70    name: 'android:windowBackground',
71    parent: styleResourceGroup,
72  });
73}
74
75export function setSplashColorsForTheme(
76  colors: AndroidConfig.Resources.ResourceXML,
77  backgroundColor: string | null
78): AndroidConfig.Resources.ResourceXML {
79  return Colors.assignColorValue(colors, { value: backgroundColor, name: SPLASH_COLOR_NAME });
80}
81