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