airship-expo-plugin
Version:
Airship Expo config plugin
150 lines (149 loc) • 6.26 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.withAirshipAndroid = void 0;
const config_plugins_1 = require("@expo/config-plugins");
const image_utils_1 = require("@expo/image-utils");
const fs_1 = require("fs");
const path_1 = require("path");
const assert_1 = __importDefault(require("assert"));
const iconSizeMap = {
mdpi: 24,
hdpi: 32,
xhdpi: 48,
xxhdpi: 72,
xxxhdpi: 96,
};
const NOTIFICATIONS_CHANNELS_FILE_NAME = "ua_custom_notification_channels.xml";
const AIRSHP_PLUGIN_EXTENDER_CLASS_NAME = "AirshipExtender";
const { addMetaDataItemToMainApplication, getMainApplicationOrThrow } = config_plugins_1.AndroidConfig.Manifest;
async function writeNotificationIconImageFilesAsync(props, projectRoot) {
const fileName = (0, path_1.basename)(props.icon);
await Promise.all(Object.entries(iconSizeMap).map(async (entry) => {
const iconSizePx = entry[1];
const resourceDir = (0, path_1.resolve)(projectRoot, 'android/app/src/main/res/', "drawable-" + entry[0]);
if (!(0, fs_1.existsSync)(resourceDir)) {
(0, fs_1.mkdirSync)(resourceDir, { recursive: true });
}
const options = {
projectRoot: projectRoot,
cacheType: 'airship'
};
const imageOptions = {
src: props.icon,
width: iconSizePx,
height: iconSizePx,
resizeMode: 'cover',
backgroundColor: 'transparent',
};
const result = await (0, image_utils_1.generateImageAsync)(options, imageOptions);
(0, fs_1.writeFileSync)((0, path_1.resolve)(resourceDir, fileName), result.source);
}));
}
;
const withNotificationIcons = (config, props) => {
return (0, config_plugins_1.withDangerousMod)(config, [
'android',
async (config) => {
await writeNotificationIconImageFilesAsync(props, config.modRequest.projectRoot);
return config;
},
]);
};
const withCompileSDKVersionFix = (config, props) => {
return (0, config_plugins_1.withProjectBuildGradle)(config, (gradle) => {
if (!gradle.modResults.contents.includes(`compileSdkVersion = 30`)) {
return gradle;
}
gradle.modResults.contents = gradle.modResults.contents.replace('compileSdkVersion = 30', 'compileSdkVersion = 31');
return gradle;
});
};
const withCustomNotificationChannels = (config, props) => {
return (0, config_plugins_1.withDangerousMod)(config, [
'android',
async (config) => {
await writeNotificationChannelsFileAsync(props, config.modRequest.projectRoot);
return config;
},
]);
};
async function writeNotificationChannelsFileAsync(props, projectRoot) {
if (!props.customNotificationChannels) {
return;
}
const xmlResPath = (0, path_1.join)(projectRoot, "android/app/src/main/res/xml");
if (!(0, fs_1.existsSync)(xmlResPath)) {
(0, fs_1.mkdirSync)(xmlResPath, { recursive: true });
}
// Copy the custom notification channels file into the Android expo project as ua_custom_notification_channels.xml.
(0, fs_1.readFile)(props.customNotificationChannels, 'utf8', (err, data) => {
if (err || !data) {
console.error("Airship couldn't read file " + props.customNotificationChannels);
console.error(err);
return;
}
(0, fs_1.writeFileSync)((0, path_1.join)(xmlResPath, NOTIFICATIONS_CHANNELS_FILE_NAME), data);
});
}
;
const withAirshipExtender = (config, props) => {
return (0, config_plugins_1.withDangerousMod)(config, [
'android',
async (config) => {
(0, assert_1.default)(config.android?.package, "Missing 'android.package' in app config.");
await writeAirshipExtenderFileAsync(props, config.modRequest.projectRoot, config.android.package);
return config;
},
]);
};
async function writeAirshipExtenderFileAsync(props, projectRoot, packageName) {
if (!props.airshipExtender) {
return;
}
const fileName = (0, path_1.basename)(props.airshipExtender);
const extenderDestinationPath = (0, path_1.join)(projectRoot, "android/app/src/main/java", packageName.split('.').join('/'));
if (!(0, fs_1.existsSync)(extenderDestinationPath)) {
(0, fs_1.mkdirSync)(extenderDestinationPath, { recursive: true });
}
// Copy the Airship Extender file into the Android expo project.
(0, fs_1.readFile)(props.airshipExtender, 'utf8', (err, data) => {
if (err || !data) {
console.error("Airship couldn't read file " + (props.airshipExtender));
console.error(err);
return;
}
(0, fs_1.writeFileSync)((0, path_1.join)(extenderDestinationPath, fileName), data);
});
}
;
const withAirshipExtenderInManifest = (config, props) => {
return (0, config_plugins_1.withAndroidManifest)(config, async (config) => {
(0, assert_1.default)(config.android?.package, "Missing 'android.package' in app config.");
config.modResults = await setCustomConfigAsync(config.android.package, config.modResults);
return config;
});
};
async function setCustomConfigAsync(packageName, androidManifest) {
// Get the <application /> tag and assert if it doesn't exist.
const mainApplication = getMainApplicationOrThrow(androidManifest);
addMetaDataItemToMainApplication(mainApplication,
// value for `android:name`
'com.urbanairship.plugin.extender',
// value for `android:value`
`${packageName}.${AIRSHP_PLUGIN_EXTENDER_CLASS_NAME}`);
return androidManifest;
}
const withAirshipAndroid = (config, props) => {
config = withCompileSDKVersionFix(config, props);
config = withNotificationIcons(config, props);
config = withCustomNotificationChannels(config, props);
if (props.airshipExtender) {
config = withAirshipExtender(config, props);
config = withAirshipExtenderInManifest(config, props);
}
return config;
};
exports.withAirshipAndroid = withAirshipAndroid;