1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3    return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6exports.setNavigationBarStyles = exports.setNavigationBarColors = exports.setStrings = exports.withAndroidNavigationBarExpoGoManifest = exports.resolveProps = void 0;
7// @ts-ignore: uses flow
8const normalize_color_1 = __importDefault(require("@react-native/normalize-color"));
9// @ts-ignore
10const debug_1 = __importDefault(require("debug"));
11const config_plugins_1 = require("expo/config-plugins");
12const debug = (0, debug_1.default)('expo:system-navigation-bar:plugin');
13const pkg = require('expo-navigation-bar/package.json');
14// strings.xml keys, this should not change.
15const BORDER_COLOR_KEY = 'expo_navigation_bar_border_color';
16const VISIBILITY_KEY = 'expo_navigation_bar_visibility';
17const POSITION_KEY = 'expo_navigation_bar_position';
18const BEHAVIOR_KEY = 'expo_navigation_bar_behavior';
19const LEGACY_VISIBLE_KEY = 'expo_navigation_bar_legacy_visible';
20// styles.xml value
21const NAVIGATION_BAR_COLOR = 'navigationBarColor';
22const LEGACY_BAR_STYLE_MAP = {
23    // Match expo-status-bar
24    'dark-content': 'dark',
25    'light-content': 'light',
26};
27function convertColorAndroid(input) {
28    let color = (0, normalize_color_1.default)(input);
29    if (!color) {
30        throw new Error('Invalid color value: ' + input);
31    }
32    color = ((color << 24) | (color >>> 8)) >>> 0;
33    // Android use 32 bit *signed* integer to represent the color
34    // We utilize the fact that bitwise operations in JS also operates on
35    // signed 32 bit integers, so that we can use those to convert from
36    // *unsigned* to *signed* 32bit int that way.
37    return color | 0x0;
38}
39function resolveProps(config, _props) {
40    let props;
41    if (!_props) {
42        props = {
43            backgroundColor: config.androidNavigationBar?.backgroundColor,
44            barStyle: config.androidNavigationBar?.barStyle
45                ? LEGACY_BAR_STYLE_MAP[config.androidNavigationBar?.barStyle]
46                : undefined,
47            // Resources for:
48            // - sticky-immersive: https://youtu.be/cBi8fjv90E4?t=416 -- https://developer.android.com/training/system-ui/immersive#sticky-immersive
49            // - immersive: https://youtu.be/cBi8fjv90E4?t=168 -- https://developer.android.com/training/system-ui/immersive#immersive
50            // - leanback: https://developer.android.com/training/system-ui/immersive#leanback
51            legacyVisible: config.androidNavigationBar?.visible,
52        };
53        if (props.legacyVisible) {
54            // Using legacyVisible can break the setPositionAsync method:
55            // https://developer.android.com/reference/androidx/core/view/WindowCompat#setDecorFitsSystemWindows(android.view.Window,%20boolean)
56            config_plugins_1.WarningAggregator.addWarningAndroid('androidNavigationBar.visible', 'property is deprecated in Android 11 (API 30) and will be removed from Expo SDK', 'https://expo.fyi/android-navigation-bar-visible-deprecated');
57        }
58    }
59    else {
60        props = _props;
61    }
62    return props;
63}
64exports.resolveProps = resolveProps;
65/**
66 * Ensure the Expo Go manifest is updated when the project is using config plugin properties instead
67 * of the static values that Expo Go reads from (`androidNavigationBar`).
68 */
69const withAndroidNavigationBarExpoGoManifest = (config, props) => {
70    if (!config.androidNavigationBar) {
71        // Remap the config plugin props so Expo Go knows how to apply them.
72        config.androidNavigationBar = {
73            backgroundColor: props.backgroundColor ?? undefined,
74            barStyle: Object.entries(LEGACY_BAR_STYLE_MAP).find(([, v]) => v === props.barStyle)?.[0],
75            visible: props.legacyVisible,
76        };
77    }
78    return config;
79};
80exports.withAndroidNavigationBarExpoGoManifest = withAndroidNavigationBarExpoGoManifest;
81const withNavigationBar = (config, _props) => {
82    const props = resolveProps(config, _props);
83    config = (0, exports.withAndroidNavigationBarExpoGoManifest)(config, props);
84    debug('Props:', props);
85    // TODO: Add this to expo/config-plugins
86    // Elevate props to a static value on extra so Expo Go can read it.
87    if (!config.extra) {
88        config.extra = {};
89    }
90    config.extra[pkg.name] = props;
91    // Use built-in styles instead of Expo custom properties, this makes the project hopefully a bit more predictable for bare users.
92    config = withNavigationBarColors(config, props);
93    config = withNavigationBarStyles(config, props);
94    return (0, config_plugins_1.withStringsXml)(config, (config) => {
95        config.modResults = setStrings(config.modResults, props);
96        return config;
97    });
98};
99function setStrings(strings, { borderColor, visibility, position, behavior, legacyVisible, }) {
100    const pairs = [
101        [BORDER_COLOR_KEY, borderColor ? convertColorAndroid(borderColor) : null],
102        [VISIBILITY_KEY, visibility],
103        [POSITION_KEY, position],
104        [BEHAVIOR_KEY, behavior],
105        [LEGACY_VISIBLE_KEY, legacyVisible],
106    ];
107    const stringItems = [];
108    for (const [key, value] of pairs) {
109        if (value == null) {
110            // Since we're using custom strings, we can remove them for convenience between prebuilds.
111            strings = config_plugins_1.AndroidConfig.Strings.removeStringItem(key, strings);
112        }
113        else {
114            stringItems.push(config_plugins_1.AndroidConfig.Resources.buildResourceItem({
115                name: key,
116                value: String(value),
117                translatable: false,
118            }));
119        }
120    }
121    return config_plugins_1.AndroidConfig.Strings.setStringItem(stringItems, strings);
122}
123exports.setStrings = setStrings;
124const withNavigationBarColors = (config, props) => {
125    return (0, config_plugins_1.withAndroidColors)(config, (config) => {
126        config.modResults = setNavigationBarColors(props, config.modResults);
127        return config;
128    });
129};
130const withNavigationBarStyles = (config, props) => {
131    return (0, config_plugins_1.withAndroidStyles)(config, (config) => {
132        config.modResults = setNavigationBarStyles(props, config.modResults);
133        return config;
134    });
135};
136function setNavigationBarColors({ backgroundColor }, colors) {
137    if (backgroundColor) {
138        colors = config_plugins_1.AndroidConfig.Colors.setColorItem(config_plugins_1.AndroidConfig.Resources.buildResourceItem({
139            name: NAVIGATION_BAR_COLOR,
140            value: backgroundColor,
141        }), colors);
142    }
143    return colors;
144}
145exports.setNavigationBarColors = setNavigationBarColors;
146function setNavigationBarStyles({ backgroundColor, barStyle }, styles) {
147    styles = config_plugins_1.AndroidConfig.Styles.assignStylesValue(styles, {
148        add: !!backgroundColor,
149        parent: config_plugins_1.AndroidConfig.Styles.getAppThemeLightNoActionBarGroup(),
150        name: `android:${NAVIGATION_BAR_COLOR}`,
151        value: `@color/${NAVIGATION_BAR_COLOR}`,
152    });
153    styles = config_plugins_1.AndroidConfig.Styles.assignStylesValue(styles, {
154        // Adding means the buttons will be darker to account for a light background color.
155        // `setButtonStyleAsync('dark')` should do the same thing.
156        add: barStyle === 'dark',
157        parent: config_plugins_1.AndroidConfig.Styles.getAppThemeLightNoActionBarGroup(),
158        name: 'android:windowLightNavigationBar',
159        value: 'true',
160    });
161    return styles;
162}
163exports.setNavigationBarStyles = setNavigationBarStyles;
164exports.default = (0, config_plugins_1.createRunOncePlugin)(withNavigationBar, pkg.name, pkg.version);
165