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