const { withMainActivity } = require('expo/config-plugins') // Why: edge-to-edge picks the navigation bar's light or dark look (and the contrast scrim drawn // behind it) once, from the phone's theme at launch (#34246). MainActivity handles uiMode itself, // so Orca's own theme choice and later phone switches never reach the bar, leaving a white scrim // under a dark app. AppCompat reports both through onConfigurationChanged with the resolved uiMode. const MARKER = 'orca: navigation bar theme' const CLASS_HEADER = 'class MainActivity : ReactActivity() {' const IMPORTS = [ 'android.content.res.Configuration', 'androidx.core.view.WindowInsetsControllerCompat' ] const INIT_BLOCK = ` // ${MARKER}, generated by plugins/android-navigation-bar-theme.js. init { addOnConfigurationChangedListener { config -> val dark = config.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES WindowInsetsControllerCompat(window, window.decorView).isAppearanceLightNavigationBars = !dark } } ` function patchMainActivity(contents) { if (contents.includes(MARKER)) { return contents } if (!contents.includes(CLASS_HEADER)) { throw new Error( "android-navigation-bar-theme: Expo's MainActivity template changed; update the plugin before building." ) } const imports = IMPORTS.filter((name) => !contents.includes(`import ${name}\n`)) .map((name) => `import ${name}\n`) .join('') return contents .replace(/^(package [^\n]+\n)/, `$1${imports}`) .replace(CLASS_HEADER, `${CLASS_HEADER}\n${INIT_BLOCK}`) } module.exports = function withAndroidNavigationBarTheme(config) { return withMainActivity(config, (cfg) => { if (cfg.modResults.language !== 'kt') { throw new Error( `android-navigation-bar-theme: expected a Kotlin MainActivity, got ${cfg.modResults.language}` ) } cfg.modResults.contents = patchMainActivity(cfg.modResults.contents) return cfg }) }