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