1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.withNotificationsAndroid = exports.setNotificationSounds = exports.setNotificationIconAsync = exports.setNotificationIconColor = exports.getNotificationColor = exports.getNotificationIcon = exports.withNotificationSounds = exports.withNotificationManifest = exports.withNotificationIconColor = exports.withNotificationIcons = exports.NOTIFICATION_ICON_COLOR_RESOURCE = exports.NOTIFICATION_ICON_COLOR = exports.NOTIFICATION_ICON_RESOURCE = exports.NOTIFICATION_ICON = exports.META_DATA_NOTIFICATION_ICON_COLOR = exports.META_DATA_NOTIFICATION_ICON = exports.dpiValues = exports.ANDROID_RES_PATH = void 0;
4const image_utils_1 = require("@expo/image-utils");
5const config_plugins_1 = require("expo/config-plugins");
6const fs_1 = require("fs");
7const path_1 = require("path");
8const { Colors } = config_plugins_1.AndroidConfig;
9exports.ANDROID_RES_PATH = 'android/app/src/main/res/';
10exports.dpiValues = {
11    mdpi: { folderName: 'mipmap-mdpi', scale: 1 },
12    hdpi: { folderName: 'mipmap-hdpi', scale: 1.5 },
13    xhdpi: { folderName: 'mipmap-xhdpi', scale: 2 },
14    xxhdpi: { folderName: 'mipmap-xxhdpi', scale: 3 },
15    xxxhdpi: { folderName: 'mipmap-xxxhdpi', scale: 4 },
16};
17const { addMetaDataItemToMainApplication, getMainApplicationOrThrow, removeMetaDataItemFromMainApplication, } = config_plugins_1.AndroidConfig.Manifest;
18const BASELINE_PIXEL_SIZE = 24;
19const ERROR_MSG_PREFIX = 'An error occurred while configuring Android notifications. ';
20exports.META_DATA_NOTIFICATION_ICON = 'expo.modules.notifications.default_notification_icon';
21exports.META_DATA_NOTIFICATION_ICON_COLOR = 'expo.modules.notifications.default_notification_color';
22exports.NOTIFICATION_ICON = 'notification_icon';
23exports.NOTIFICATION_ICON_RESOURCE = `@drawable/${exports.NOTIFICATION_ICON}`;
24exports.NOTIFICATION_ICON_COLOR = 'notification_icon_color';
25exports.NOTIFICATION_ICON_COLOR_RESOURCE = `@color/${exports.NOTIFICATION_ICON_COLOR}`;
26const withNotificationIcons = (config, { icon }) => {
27    // If no icon provided in the config plugin props, fallback to value from app.json
28    icon = icon || getNotificationIcon(config);
29    return (0, config_plugins_1.withDangerousMod)(config, [
30        'android',
31        async (config) => {
32            await setNotificationIconAsync(config.modRequest.projectRoot, icon);
33            return config;
34        },
35    ]);
36};
37exports.withNotificationIcons = withNotificationIcons;
38const withNotificationIconColor = (config, { color }) => {
39    // If no color provided in the config plugin props, fallback to value from app.json
40    return (0, config_plugins_1.withAndroidColors)(config, (config) => {
41        color = color || getNotificationColor(config);
42        config.modResults = setNotificationIconColor(color, config.modResults);
43        return config;
44    });
45};
46exports.withNotificationIconColor = withNotificationIconColor;
47const withNotificationManifest = (config, { icon, color }) => {
48    // If no icon or color provided in the config plugin props, fallback to value from app.json
49    icon = icon || getNotificationIcon(config);
50    color = color || getNotificationColor(config);
51    return (0, config_plugins_1.withAndroidManifest)(config, (config) => {
52        config.modResults = setNotificationConfig({ icon, color }, config.modResults);
53        return config;
54    });
55};
56exports.withNotificationManifest = withNotificationManifest;
57const withNotificationSounds = (config, { sounds }) => {
58    return (0, config_plugins_1.withDangerousMod)(config, [
59        'android',
60        (config) => {
61            setNotificationSounds(config.modRequest.projectRoot, sounds);
62            return config;
63        },
64    ]);
65};
66exports.withNotificationSounds = withNotificationSounds;
67function getNotificationIcon(config) {
68    return config.notification?.icon || null;
69}
70exports.getNotificationIcon = getNotificationIcon;
71function getNotificationColor(config) {
72    return config.notification?.color || null;
73}
74exports.getNotificationColor = getNotificationColor;
75function setNotificationIconColor(color, colors) {
76    return Colors.assignColorValue(colors, {
77        name: exports.NOTIFICATION_ICON_COLOR,
78        value: color,
79    });
80}
81exports.setNotificationIconColor = setNotificationIconColor;
82/**
83 * Applies notification icon configuration for expo-notifications
84 */
85async function setNotificationIconAsync(projectRoot, icon) {
86    if (icon) {
87        await writeNotificationIconImageFilesAsync(icon, projectRoot);
88    }
89    else {
90        removeNotificationIconImageFiles(projectRoot);
91    }
92}
93exports.setNotificationIconAsync = setNotificationIconAsync;
94function setNotificationConfig(props, manifest) {
95    const mainApplication = getMainApplicationOrThrow(manifest);
96    if (props.icon) {
97        addMetaDataItemToMainApplication(mainApplication, exports.META_DATA_NOTIFICATION_ICON, exports.NOTIFICATION_ICON_RESOURCE, 'resource');
98    }
99    else {
100        removeMetaDataItemFromMainApplication(mainApplication, exports.META_DATA_NOTIFICATION_ICON);
101    }
102    if (props.color) {
103        addMetaDataItemToMainApplication(mainApplication, exports.META_DATA_NOTIFICATION_ICON_COLOR, exports.NOTIFICATION_ICON_COLOR_RESOURCE, 'resource');
104    }
105    else {
106        removeMetaDataItemFromMainApplication(mainApplication, exports.META_DATA_NOTIFICATION_ICON_COLOR);
107    }
108    return manifest;
109}
110async function writeNotificationIconImageFilesAsync(icon, projectRoot) {
111    await Promise.all(Object.values(exports.dpiValues).map(async ({ folderName, scale }) => {
112        const drawableFolderName = folderName.replace('mipmap', 'drawable');
113        const dpiFolderPath = (0, path_1.resolve)(projectRoot, exports.ANDROID_RES_PATH, drawableFolderName);
114        if (!(0, fs_1.existsSync)(dpiFolderPath)) {
115            (0, fs_1.mkdirSync)(dpiFolderPath, { recursive: true });
116        }
117        const iconSizePx = BASELINE_PIXEL_SIZE * scale;
118        try {
119            const resizedIcon = (await (0, image_utils_1.generateImageAsync)({ projectRoot, cacheType: 'android-notification' }, {
120                src: icon,
121                width: iconSizePx,
122                height: iconSizePx,
123                resizeMode: 'cover',
124                backgroundColor: 'transparent',
125            })).source;
126            (0, fs_1.writeFileSync)((0, path_1.resolve)(dpiFolderPath, exports.NOTIFICATION_ICON + '.png'), resizedIcon);
127        }
128        catch (e) {
129            throw new Error(ERROR_MSG_PREFIX + 'Encountered an issue resizing Android notification icon: ' + e);
130        }
131    }));
132}
133function removeNotificationIconImageFiles(projectRoot) {
134    Object.values(exports.dpiValues).forEach(async ({ folderName }) => {
135        const drawableFolderName = folderName.replace('mipmap', 'drawable');
136        const dpiFolderPath = (0, path_1.resolve)(projectRoot, exports.ANDROID_RES_PATH, drawableFolderName);
137        const iconFile = (0, path_1.resolve)(dpiFolderPath, exports.NOTIFICATION_ICON + '.png');
138        if ((0, fs_1.existsSync)(iconFile)) {
139            (0, fs_1.unlinkSync)(iconFile);
140        }
141    });
142}
143/**
144 * Save sound files to `<project-root>/android/app/src/main/res/raw`
145 */
146function setNotificationSounds(projectRoot, sounds) {
147    if (!Array.isArray(sounds)) {
148        throw new Error(ERROR_MSG_PREFIX +
149            `Must provide an array of sound files in your app config, found ${typeof sounds}.`);
150    }
151    for (const soundFileRelativePath of sounds) {
152        writeNotificationSoundFile(soundFileRelativePath, projectRoot);
153    }
154}
155exports.setNotificationSounds = setNotificationSounds;
156/**
157 * Copies the input file to the `<project-root>/android/app/src/main/res/raw` directory if
158 * there isn't already an existing file under that name.
159 */
160function writeNotificationSoundFile(soundFileRelativePath, projectRoot) {
161    const rawResourcesPath = (0, path_1.resolve)(projectRoot, exports.ANDROID_RES_PATH, 'raw');
162    const inputFilename = (0, path_1.basename)(soundFileRelativePath);
163    if (inputFilename) {
164        try {
165            const sourceFilepath = (0, path_1.resolve)(projectRoot, soundFileRelativePath);
166            const destinationFilepath = (0, path_1.resolve)(rawResourcesPath, inputFilename);
167            if (!(0, fs_1.existsSync)(rawResourcesPath)) {
168                (0, fs_1.mkdirSync)(rawResourcesPath, { recursive: true });
169            }
170            (0, fs_1.copyFileSync)(sourceFilepath, destinationFilepath);
171        }
172        catch (e) {
173            throw new Error(ERROR_MSG_PREFIX + 'Encountered an issue copying Android notification sounds: ' + e);
174        }
175    }
176}
177const withNotificationsAndroid = (config, { icon = null, color = null, sounds = [] }) => {
178    config = (0, exports.withNotificationIconColor)(config, { color });
179    config = (0, exports.withNotificationIcons)(config, { icon });
180    config = (0, exports.withNotificationManifest)(config, { icon, color });
181    config = (0, exports.withNotificationSounds)(config, { sounds });
182    return config;
183};
184exports.withNotificationsAndroid = withNotificationsAndroid;
185