Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Features/webp support for splashscreen #1113

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 34 additions & 55 deletions bin/templates/cordova/lib/prepare.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,11 +302,12 @@ function default_versionCode (version) {
}

function getImageResourcePath (resourcesDir, type, density, name, sourceName) {
if (/\.9\.png$/.test(sourceName)) {
name = name.replace(/\.png$/, '.9.png');
}
var resourcePath = path.join(resourcesDir, (density ? type + '-' + density : type), name);
return resourcePath;
// Use same extension as source with special case for 9-Patch files
const ext = sourceName.endsWith('.9.png')
? '.9.png' : path.extname(sourceName).toLowerCase();

const subDir = density ? `${type}-${density}` : type;
return path.join(resourcesDir, subDir, name + ext);
}

function getAdaptiveImageResourcePath (resourcesDir, type, density, name, sourceName) {
Expand All @@ -317,28 +318,13 @@ function getAdaptiveImageResourcePath (resourcesDir, type, density, name, source
return resourcePath;
}

/**
* The splashScreenSrc is a .webp image or a .png (or .jpg) image.
* An inputted .webp should be copied to a screen.webp file.
* An inputted .png (or .jpg) should be copied to a screen.png file.
*
* When a splashscreen is changed from a .png to a .webp or the other way round,
* the other image must be deleted, to avoid a duplicate resource exception.
*
* @param splashScreenSrc
* @returns {{splashScreenDestToRemove: string, splashScreenDest: string}}
*/
function buildSplashScreenImageToCopyAndToRemove (splashScreenSrc) {
if (path.extname(splashScreenSrc) === '.webp') {
return {
splashScreenDest: 'screen.webp',
splashScreenDestToRemove: 'screen.png'
};
}
return {
splashScreenDest: 'screen.png',
splashScreenDestToRemove: 'screen.webp'
};
function makeSplashCleanupMap (projectRoot, resourcesDir) {
// Build an initial resource map that deletes all existing splash screens
const existingSplashPaths = glob.sync(
PieterVanPoyer marked this conversation as resolved.
Show resolved Hide resolved
`${resourcesDir}/drawable-*/screen.{png,9.png,webp,jpg,jpeg}`,
{ cwd: projectRoot }
);
return makeCleanResourceMap(existingSplashPaths);
}

function updateSplashes (cordovaProject, platformResourcesDir) {
Expand All @@ -350,7 +336,8 @@ function updateSplashes (cordovaProject, platformResourcesDir) {
return;
}

var resourceMap = mapImageResources(cordovaProject.root, platformResourcesDir, 'drawable', 'screen.png');
// Build an initial resource map that deletes all existing splash screens
const resourceMap = makeSplashCleanupMap(cordovaProject.root, platformResourcesDir);

var hadMdpi = false;
resources.forEach(function (resource) {
Expand All @@ -360,28 +347,16 @@ function updateSplashes (cordovaProject, platformResourcesDir) {
if (resource.density === 'mdpi') {
hadMdpi = true;
}
const splashScreenToCopyAndRemove = buildSplashScreenImageToCopyAndToRemove(resource.src);

const targetPath = getImageResourcePath(platformResourcesDir, 'drawable', resource.density,
splashScreenToCopyAndRemove.splashScreenDest, path.basename(resource.src));
var targetPath = getImageResourcePath(
platformResourcesDir, 'drawable', resource.density, 'screen', path.basename(resource.src));
resourceMap[targetPath] = resource.src;

const targetPathToDelete = getImageResourcePath(platformResourcesDir, 'drawable', resource.density,
splashScreenToCopyAndRemove.splashScreenDestToRemove, path.basename(resource.src));
resourceMap[targetPathToDelete] = null;
});

// There's no "default" drawable, so assume default == mdpi.
if (!hadMdpi && resources.defaultResource) {
const splashScreenToCopyAndRemove = buildSplashScreenImageToCopyAndToRemove(resources.defaultResource.src);

const targetPath = getImageResourcePath(platformResourcesDir, 'drawable', 'mdpi',
splashScreenToCopyAndRemove.splashScreenDest, path.basename(resources.defaultResource.src));
var targetPath = getImageResourcePath(
platformResourcesDir, 'drawable', 'mdpi', 'screen', path.basename(resources.defaultResource.src));
resourceMap[targetPath] = resources.defaultResource.src;

const targetPathToDelete = getImageResourcePath(platformResourcesDir, 'drawable', 'mdpi',
splashScreenToCopyAndRemove.splashScreenDestToRemove, path.basename(resources.defaultResource.src));
resourceMap[targetPathToDelete] = null;
}

events.emit('verbose', 'Updating splash screens at ' + platformResourcesDir);
Expand All @@ -392,19 +367,13 @@ function updateSplashes (cordovaProject, platformResourcesDir) {
function cleanSplashes (projectRoot, projectConfig, platformResourcesDir) {
var resources = projectConfig.getSplashScreens('android');
if (resources.length > 0) {
const pngResourceMap = mapImageResources(projectRoot, platformResourcesDir, 'drawable', 'screen.png');
events.emit('verbose', 'Cleaning png splash screens at ' + platformResourcesDir);

// No source paths are specified in the map, so updatePaths() will delete the target files.
FileUpdater.updatePaths(
pngResourceMap, { rootDir: projectRoot, all: true }, logFileOp);
const resourceMap = makeSplashCleanupMap(projectRoot, platformResourcesDir);

const webpResourceMap = mapImageResources(projectRoot, platformResourcesDir, 'drawable', 'screen.webp');
events.emit('verbose', 'Cleaning webp splash screens at ' + platformResourcesDir);
events.emit('verbose', 'Cleaning splash screens at ' + platformResourcesDir);

// No source paths are specified in the map, so updatePaths() will delete the target files.
FileUpdater.updatePaths(
webpResourceMap, { rootDir: projectRoot, all: true }, logFileOp);
resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
}
}

Expand Down Expand Up @@ -589,13 +558,13 @@ function updateIconResourceForLegacy (preparedIcons, resourceMap, platformResour
// The source paths for icons and splashes are relative to
// project's config.xml location, so we use it as base path.
for (var density in android_icons) {
var targetPath = getImageResourcePath(platformResourcesDir, 'mipmap', density, 'ic_launcher.png', path.basename(android_icons[density].src));
var targetPath = getImageResourcePath(platformResourcesDir, 'mipmap', density, 'ic_launcher', path.basename(android_icons[density].src));
resourceMap[targetPath] = android_icons[density].src;
}

// There's no "default" drawable, so assume default == mdpi.
if (default_icon && !android_icons.mdpi) {
var defaultTargetPath = getImageResourcePath(platformResourcesDir, 'mipmap', 'mdpi', 'ic_launcher.png', path.basename(default_icon.src));
var defaultTargetPath = getImageResourcePath(platformResourcesDir, 'mipmap', 'mdpi', 'ic_launcher', path.basename(default_icon.src));
resourceMap[defaultTargetPath] = default_icon.src;
}

Expand Down Expand Up @@ -715,6 +684,16 @@ function mapImageResources (rootDir, subDir, type, resourceName) {
return pathMap;
}

/** Returns resource map that deletes all given paths */
function makeCleanResourceMap (resourcePaths) {
const pathMap = {};
resourcePaths.map(path.normalize)
.forEach(resourcePath => {
pathMap[resourcePath] = null;
});
return pathMap;
}

function updateFileResources (cordovaProject, platformDir) {
var files = cordovaProject.projectConfig.getFileResources('android');

Expand Down
11 changes: 4 additions & 7 deletions spec/unit/prepare.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -885,13 +885,10 @@ describe('prepare', () => {
});

// mocking initial responses for mapImageResources
prepare.__set__('mapImageResources', function (rootDir, subDir, type, resourceName) {
if (resourceName.includes('screen.png')) {
return createResourceMap('screen.png');
} else if (resourceName.includes('screen.webp')) {
return createResourceMap('screen.webp');
}
});
prepare.__set__('makeSplashCleanupMap', (rootDir, resourcesDir) => ({
[path.join(resourcesDir, 'drawable-mdpi/screen.png')]: null,
[path.join(resourcesDir, 'drawable-mdpi/screen.webp')]: null
}));
});

it('Test#001 : Should detect no defined splash screens.', function () {
Expand Down