1import assert from 'assert';
2import { ExpoConfig } from 'expo/config';
3import { AndroidConfig, ConfigPlugin, withStringsXml } from 'expo/config-plugins';
4
5export type Props = {
6  userInterfaceStyle?: ExpoConfig['userInterfaceStyle'];
7};
8
9// strings.xml keys, this should not change.
10const USER_INTERFACE_STYLE_KEY = 'expo_system_ui_user_interface_style';
11
12export const withAndroidUserInterfaceStyle: ConfigPlugin<void> = (config) => {
13  return withStringsXml(config, (config) => {
14    config.modResults = setStrings(config.modResults, resolveProps(config));
15    return config;
16  });
17};
18
19export function resolveProps(config: Pick<ExpoConfig, 'userInterfaceStyle' | 'android'>): Props {
20  const userInterfaceStyle = config.android?.userInterfaceStyle ?? config.userInterfaceStyle;
21
22  assert(
23    !userInterfaceStyle || ['automatic', 'light', 'dark'].includes(userInterfaceStyle),
24    `expo-system-ui: Invalid userInterfaceStyle: "${userInterfaceStyle}"`
25  );
26
27  return { userInterfaceStyle };
28}
29
30export function setStrings(
31  strings: AndroidConfig.Resources.ResourceXML,
32  { userInterfaceStyle }: Props
33): AndroidConfig.Resources.ResourceXML {
34  const pairs = [[USER_INTERFACE_STYLE_KEY, userInterfaceStyle]] as [string, any][];
35
36  const stringItems: AndroidConfig.Resources.ResourceItemXML[] = [];
37  for (const [key, value] of pairs) {
38    if (value == null) {
39      // Since we're using custom strings, we can remove them for convenience between prebuilds.
40      strings = AndroidConfig.Strings.removeStringItem(key, strings);
41    } else {
42      stringItems.push(
43        AndroidConfig.Resources.buildResourceItem({
44          name: key,
45          value: String(value),
46          translatable: false,
47        })
48      );
49    }
50  }
51
52  return AndroidConfig.Strings.setStringItem(stringItems, strings);
53}
54