1082815dcSEvan Baconimport { ExpoConfig } from '@expo/config-types'; 2082815dcSEvan Baconimport assert from 'assert'; 3082815dcSEvan Bacon 4082815dcSEvan Baconimport { assignColorValue } from './Colors'; 5082815dcSEvan Baconimport { ResourceXML } from './Resources'; 6082815dcSEvan Baconimport { assignStylesValue, getAppThemeLightNoActionBarGroup } from './Styles'; 7*8a424bebSJames Ideimport { ConfigPlugin } from '../Plugin.types'; 8*8a424bebSJames Ideimport { withAndroidColors, withAndroidStyles } from '../plugins/android-plugins'; 9082815dcSEvan Bacon 10082815dcSEvan Bacon// https://developer.android.com/reference/android/R.attr#colorPrimaryDark 11082815dcSEvan Baconconst COLOR_PRIMARY_DARK_KEY = 'colorPrimaryDark'; 12082815dcSEvan Bacon// https://developer.android.com/reference/android/R.attr#windowTranslucentStatus 13082815dcSEvan Baconconst WINDOW_TRANSLUCENT_STATUS = 'android:windowTranslucentStatus'; 14082815dcSEvan Bacon// https://developer.android.com/reference/android/R.attr#windowLightStatusBar 15082815dcSEvan Baconconst WINDOW_LIGHT_STATUS_BAR = 'android:windowLightStatusBar'; 16082815dcSEvan Bacon 17082815dcSEvan Baconexport const withStatusBar: ConfigPlugin = (config) => { 18082815dcSEvan Bacon config = withStatusBarColors(config); 19082815dcSEvan Bacon config = withStatusBarStyles(config); 20082815dcSEvan Bacon return config; 21082815dcSEvan Bacon}; 22082815dcSEvan Bacon 23082815dcSEvan Baconconst withStatusBarColors: ConfigPlugin = (config) => { 24082815dcSEvan Bacon return withAndroidColors(config, (config) => { 25082815dcSEvan Bacon config.modResults = setStatusBarColors(config, config.modResults); 26082815dcSEvan Bacon return config; 27082815dcSEvan Bacon }); 28082815dcSEvan Bacon}; 29082815dcSEvan Bacon 30082815dcSEvan Baconconst withStatusBarStyles: ConfigPlugin = (config) => { 31082815dcSEvan Bacon return withAndroidStyles(config, (config) => { 32082815dcSEvan Bacon config.modResults = setStatusBarStyles(config, config.modResults); 33082815dcSEvan Bacon return config; 34082815dcSEvan Bacon }); 35082815dcSEvan Bacon}; 36082815dcSEvan Bacon 37082815dcSEvan Baconexport function setStatusBarColors( 38082815dcSEvan Bacon config: Pick<ExpoConfig, 'androidStatusBar'>, 39082815dcSEvan Bacon colors: ResourceXML 40082815dcSEvan Bacon): ResourceXML { 41082815dcSEvan Bacon return assignColorValue(colors, { 42082815dcSEvan Bacon name: COLOR_PRIMARY_DARK_KEY, 43082815dcSEvan Bacon value: getStatusBarColor(config), 44082815dcSEvan Bacon }); 45082815dcSEvan Bacon} 46082815dcSEvan Bacon 47082815dcSEvan Baconexport function setStatusBarStyles( 48082815dcSEvan Bacon config: Pick<ExpoConfig, 'androidStatusBar'>, 49082815dcSEvan Bacon styles: ResourceXML 50082815dcSEvan Bacon): ResourceXML { 51082815dcSEvan Bacon const hexString = getStatusBarColor(config); 52082815dcSEvan Bacon const floatElement = getStatusBarTranslucent(config); 53082815dcSEvan Bacon 54082815dcSEvan Bacon styles = assignStylesValue(styles, { 55082815dcSEvan Bacon parent: getAppThemeLightNoActionBarGroup(), 56082815dcSEvan Bacon name: WINDOW_LIGHT_STATUS_BAR, 57082815dcSEvan Bacon targetApi: '23', 58082815dcSEvan Bacon value: 'true', 59082815dcSEvan Bacon // Default is light-content, don't need to do anything to set it 60082815dcSEvan Bacon add: getStatusBarStyle(config) === 'dark-content', 61082815dcSEvan Bacon }); 62082815dcSEvan Bacon 63082815dcSEvan Bacon styles = assignStylesValue(styles, { 64082815dcSEvan Bacon parent: getAppThemeLightNoActionBarGroup(), 65082815dcSEvan Bacon name: WINDOW_TRANSLUCENT_STATUS, 66082815dcSEvan Bacon value: 'true', 67082815dcSEvan Bacon // translucent status bar set in theme 68082815dcSEvan Bacon add: floatElement, 69082815dcSEvan Bacon }); 70082815dcSEvan Bacon 71082815dcSEvan Bacon styles = assignStylesValue(styles, { 72082815dcSEvan Bacon parent: getAppThemeLightNoActionBarGroup(), 73082815dcSEvan Bacon name: COLOR_PRIMARY_DARK_KEY, 74082815dcSEvan Bacon value: `@color/${COLOR_PRIMARY_DARK_KEY}`, 75082815dcSEvan Bacon // Remove the color if translucent is used 76082815dcSEvan Bacon add: !!hexString, 77082815dcSEvan Bacon }); 78082815dcSEvan Bacon 79082815dcSEvan Bacon return styles; 80082815dcSEvan Bacon} 81082815dcSEvan Bacon 82082815dcSEvan Baconexport function getStatusBarColor(config: Pick<ExpoConfig, 'androidStatusBar'>) { 83082815dcSEvan Bacon const backgroundColor = config.androidStatusBar?.backgroundColor; 84082815dcSEvan Bacon if (backgroundColor) { 85082815dcSEvan Bacon // Drop support for translucent 86082815dcSEvan Bacon assert( 87082815dcSEvan Bacon backgroundColor !== 'translucent', 88082815dcSEvan Bacon `androidStatusBar.backgroundColor must be a valid hex string, instead got: "${backgroundColor}"` 89082815dcSEvan Bacon ); 90082815dcSEvan Bacon } 91082815dcSEvan Bacon return backgroundColor; 92082815dcSEvan Bacon} 93082815dcSEvan Bacon 94082815dcSEvan Bacon/** 95082815dcSEvan Bacon * Specifies whether the status bar should be "translucent". When true, the status bar is drawn with `position: absolute` and a gray underlay, when false `position: relative` (pushes content down). 96082815dcSEvan Bacon * 97082815dcSEvan Bacon * @default false 98082815dcSEvan Bacon * @param config 99082815dcSEvan Bacon * @returns 100082815dcSEvan Bacon */ 101082815dcSEvan Baconexport function getStatusBarTranslucent(config: Pick<ExpoConfig, 'androidStatusBar'>): boolean { 102082815dcSEvan Bacon return config.androidStatusBar?.translucent ?? false; 103082815dcSEvan Bacon} 104082815dcSEvan Bacon 105082815dcSEvan Baconexport function getStatusBarStyle(config: Pick<ExpoConfig, 'androidStatusBar'>) { 106082815dcSEvan Bacon return config.androidStatusBar?.barStyle || 'light-content'; 107082815dcSEvan Bacon} 108