-
-
Notifications
You must be signed in to change notification settings - Fork 7
/
generate-app-icon.js
129 lines (114 loc) · 4.59 KB
/
generate-app-icon.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
const puppeteer = require('puppeteer-core');
const { compressSync } = require('fflate');
const base64 = require('base64-js');
const path = require('path');
const extractZip = require('extract-zip');
const del = require('del');
const { readdirSync } = require('fs');
const { copySync: cpSync } = require('fs-extra');
const textEncoder = new TextEncoder();
const androidAssets = [
'play_store_512.png',
path.join('res', 'mipmap-anydpi-v26'),
path.join('res', 'mipmap-hdpi'),
path.join('res', 'mipmap-mdpi'),
path.join('res', 'mipmap-xhdpi'),
path.join('res', 'mipmap-xxhdpi'),
path.join('res', 'mipmap-xxxhdpi'),
];
const androidMainFolder = (p) => path.join(__dirname, 'android', 'app', 'src', 'main', p);
const iosMainFolder = (p) => path.join(__dirname, 'ios', 'App', p);
const destAssetPaths = {
'ios': (p) => iosMainFolder(path.join('App', 'Assets.xcassets', 'AppIcon.appiconset', p)),
'android': androidMainFolder,
'web': (p) => path.join(__dirname, 'public', 'icons', p)
}
const destAssetsIgnoreList = {
'web': ['README.md']
}
const toBeDeletedWeb = [path.join('public', 'icons')];
const toBeDeletedAndroid = androidAssets.map(androidMainFolder);
const toBeDeletedIos = [path.join('App', 'Assets.xcassets', 'AppIcon.appiconset', '*')].map(iosMainFolder);
function configToUrl(config) {
return encodeURIComponent(base64.fromByteArray(
compressSync(textEncoder.encode(JSON.stringify(config)), { mtime: 0 })
));
}
async function downloadAsset(config) {
console.log('> Generating assets...');
const downloadPath = path.join(__dirname, '.cache');
const browser = await puppeteer.launch({
args: ['--no-sandbox'],
executablePath: process.env.PUPPETEER_EXEC_PATH,
headless: false
});
const page = await browser.newPage();
const configHash = configToUrl(config);
await page.goto(`https://icon.kitchen/i/${configHash}`);
const client = await page.target().createCDPSession();
const iconUploadHandle = await page.$('[data-type="image"] input[type="file"]');
// upload icon and download assets
if (iconUploadHandle) {
await iconUploadHandle.uploadFile(path.relative(process.cwd(), path.join(__dirname, 'resources', 'icon-foreground.png')));
await client.send('Page.setDownloadBehavior', {
behavior: 'allow',
downloadPath
});
console.log('> Downloading assets...');
await page.click('[aria-label="Download"]');
await page.waitForTimeout(3000);
}
return downloadPath;
}
async function extractDownloadedAsset(downloadPath) {
console.log('> Extracting zip content...');
// extract zip
const extractedFolder = path.join(downloadPath, 'extracted');
const zipFileName = 'IconKitchen-Output.zip';
await extractZip(path.join(downloadPath, zipFileName), { dir: extractedFolder });
return extractedFolder;
}
async function copyAssets(extractedFolder) {
for (const platform in destAssetPaths) {
console.log(`> Copying ${platform} assets...`);
const assetPaths = readdirSync(path.join(extractedFolder, platform));
for (let i = 0; i < assetPaths.length; i++) {
const assetPath = assetPaths[i];
if (destAssetsIgnoreList[platform] && destAssetsIgnoreList[platform].includes(assetPath)) {
continue;
}
const src = path.join(extractedFolder, platform, assetPath);
const dest = destAssetPaths[platform](assetPath);
console.log(`> (${i + 1}/${assetPaths.length}) Copying ${src} to ${dest}...`);
cpSync(src, dest, { recursive: true });
}
}
}
(async () => {
let success = true;
await del(['.cache', ...toBeDeletedWeb, ...toBeDeletedAndroid, ...toBeDeletedIos], { cwd: __dirname });
try {
const downloadPath = await downloadAsset({
values: {
fgType: 'image',
fgMask: false,
bgType: 'gradient',
fgPadding: { top: 0, right: 0, bottom: 0, left: 0 },
bgShape: 'circle',
fgScaling: 'center',
bgGradient: { color1: '#e65b7a', color2: '#f1a2b3', angle: -45 }
},
modules: ['android', 'ios', 'web']
});
const extractedFolder = await extractDownloadedAsset(downloadPath);
copyAssets(extractedFolder);
} catch (e) {
success = false;
console.error(e);
} finally {
console.log('> Deleting cache...');
await del(['.cache'], { cwd: __dirname });
console.log('> Done!');
process.exit(success ? 0 : 1);
}
})();