Skip to content

Commit 2c19107

Browse files
authored
fix: properly configure the single 1024x1024 iOS icon (#560)
1 parent 136470d commit 2c19107

File tree

9 files changed

+31
-344
lines changed

9 files changed

+31
-344
lines changed

package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/definitions.ts

-6
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ export interface Assets {
1212
iosIcon?: InputAsset | null;
1313
iosSplash?: InputAsset | null;
1414
iosSplashDark?: InputAsset | null;
15-
iosNotificationIcon?: InputAsset | null;
16-
iosSettingsIcon?: InputAsset | null;
17-
iosSpotlightIcon?: InputAsset | null;
1815

1916
androidIcon?: InputAsset | null;
2017
androidIconForeground?: InputAsset | null;
@@ -37,8 +34,6 @@ export const enum AssetKind {
3734
IconForeground = 'icon-foreground',
3835
IconBackground = 'icon-background',
3936
NotificationIcon = 'notification-icon',
40-
SettingsIcon = 'settings-icon',
41-
SpotlightIcon = 'spotlight-icon',
4237
Splash = 'splash',
4338
SplashDark = 'splash-dark',
4439
}
@@ -129,7 +124,6 @@ export interface IosOutputAssetTemplate extends OutputAssetTemplate {
129124
// https://developer.apple.com/library/archive/documentation/Xcode/Reference/xcode_ref-Asset_Catalog_Format/ImageSetType.html#//apple_ref/doc/uid/TP40015170-CH25-SW2
130125
export const enum IosIdiom {
131126
Universal = 'universal',
132-
iOSMarketing = 'ios-marketing',
133127
iPhone = 'iphone',
134128
iPad = 'ipad',
135129
Watch = 'watch',

src/platforms/ios/assets.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,16 @@ import { AssetKind, Format, IosIdiom, Orientation, Platform, Theme } from '../..
44
/**
55
* 1024px Icon
66
*
7-
* - App Store
7+
* - iOS 1024 icon
88
*/
99
export const IOS_1024_ICON: IosOutputAssetTemplate = {
1010
platform: Platform.Ios,
11-
idiom: IosIdiom.iOSMarketing,
11+
idiom: IosIdiom.Universal,
1212
kind: AssetKind.Icon,
1313
1414
format: Format.Png,
1515
width: 1024,
1616
height: 1024,
17-
scale: 1,
1817
};
1918

2019
export const IOS_1X_UNIVERSAL_ANYANY_SPLASH: IosOutputAssetTemplateSplash = {

src/platforms/ios/index.ts

+19-61
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { readFile, writeFile } from '@ionic/utils-fs';
1+
import { readFile, rmSync, writeFile } from '@ionic/utils-fs';
22
import { join } from 'path';
33
import sharp from 'sharp';
44

@@ -48,15 +48,6 @@ export class IosAssetGenerator extends AssetGenerator {
4848
return this.generateFromLogo(asset, project);
4949
case AssetKind.Icon:
5050
return this.generateIcons(asset, project);
51-
case AssetKind.NotificationIcon:
52-
return this.generateNotificationIcons(asset, project);
53-
// eslint-disable-next-line no-duplicate-case
54-
case AssetKind.Icon:
55-
return [];
56-
case AssetKind.SettingsIcon:
57-
return this.generateSettingsIcons(asset, project);
58-
case AssetKind.SpotlightIcon:
59-
return this.generateSpotlightIcons(asset, project);
6051
case AssetKind.Splash:
6152
case AssetKind.SplashDark:
6253
return this.generateSplashes(asset, project);
@@ -221,39 +212,13 @@ export class IosAssetGenerator extends AssetGenerator {
221212

222213
// Generate ALL the icons when only given a logo
223214
private async generateIconsForLogo(asset: InputAsset, project: Project): Promise<OutputAsset[]> {
224-
const icons = Object.values(IosAssetTemplates).filter((a) =>
225-
[AssetKind.Icon, AssetKind.NotificationIcon, AssetKind.SettingsIcon, AssetKind.SpotlightIcon].find(
226-
(i) => i === a.kind,
227-
),
228-
);
215+
const icons = Object.values(IosAssetTemplates).filter((a) => [AssetKind.Icon].find((i) => i === a.kind));
229216

230217
return this._generateIcons(asset, project, icons as IosOutputAssetTemplate[]);
231218
}
232219

233220
private async generateIcons(asset: InputAsset, project: Project): Promise<OutputAsset[]> {
234-
const icons = Object.values(IosAssetTemplates).filter((a) =>
235-
[AssetKind.Icon, AssetKind.NotificationIcon, AssetKind.SettingsIcon, AssetKind.SpotlightIcon].find(
236-
(i) => i === a.kind,
237-
),
238-
);
239-
240-
return this._generateIcons(asset, project, icons as IosOutputAssetTemplate[]);
241-
}
242-
243-
private async generateNotificationIcons(asset: InputAsset, project: Project): Promise<OutputAsset[]> {
244-
const icons = Object.values(IosAssetTemplates).filter((a) => a.kind === AssetKind.NotificationIcon);
245-
246-
return this._generateIcons(asset, project, icons as IosOutputAssetTemplate[]);
247-
}
248-
249-
private async generateSettingsIcons(asset: InputAsset, project: Project): Promise<OutputAsset[]> {
250-
const icons = Object.values(IosAssetTemplates).filter((a) => a.kind === AssetKind.SettingsIcon);
251-
252-
return this._generateIcons(asset, project, icons as IosOutputAssetTemplate[]);
253-
}
254-
255-
private async generateSpotlightIcons(asset: InputAsset, project: Project): Promise<OutputAsset[]> {
256-
const icons = Object.values(IosAssetTemplates).filter((a) => a.kind === AssetKind.SpotlightIcon);
221+
const icons = Object.values(IosAssetTemplates).filter((a) => [AssetKind.Icon].find((i) => i === a.kind));
257222

258223
return this._generateIcons(asset, project, icons as IosOutputAssetTemplate[]);
259224
}
@@ -308,36 +273,29 @@ export class IosAssetGenerator extends AssetGenerator {
308273
}
309274

310275
private async updateIconsContentsJson(generated: OutputAsset[], project: Project) {
311-
const contentsJsonPath = join(project.config.ios!.path!, IOS_APP_ICON_SET_PATH, 'Contents.json');
276+
const assetsPath = join(project.config.ios!.path!, IOS_APP_ICON_SET_PATH);
277+
const contentsJsonPath = join(assetsPath, 'Contents.json');
312278
const json = await readFile(contentsJsonPath, { encoding: 'utf-8' });
313279

314280
const parsed = JSON.parse(json);
315281

316-
const withoutMissing = parsed.images.filter((i: any) => !!i.filename);
317-
282+
const withoutMissing = [];
318283
for (const g of generated) {
319-
const width = g.template.width / (g.template.scale ?? 1);
320-
const height = g.template.height / (g.template.scale ?? 1);
321-
const scale = g.template.scale ?? 1;
284+
const width = g.template.width;
285+
const height = g.template.height;
322286

323-
const existing = withoutMissing.find(
324-
(f: any) =>
325-
f.scale === `${scale}x` &&
326-
f.size === `${width}x${height}` &&
327-
f.idiom === (g.template as IosOutputAssetTemplate).idiom &&
328-
typeof f.appearances === 'undefined',
329-
);
287+
parsed.images.map((i: any) => {
288+
if (i.filename !== (g.template as IosOutputAssetTemplate).name) {
289+
rmSync(join(assetsPath, i.filename));
290+
}
291+
});
330292

331-
if (existing) {
332-
existing.filename = (g.template as IosOutputAssetTemplate).name;
333-
} else {
334-
withoutMissing.push({
335-
idiom: (g.template as IosOutputAssetTemplate).idiom,
336-
size: `${width}x${height}`,
337-
scale: `${scale}x`,
338-
filename: (g.template as IosOutputAssetTemplate).name,
339-
});
340-
}
293+
withoutMissing.push({
294+
idiom: (g.template as IosOutputAssetTemplate).idiom,
295+
size: `${width}x${height}`,
296+
filename: (g.template as IosOutputAssetTemplate).name,
297+
platform: Platform.Ios,
298+
});
341299
}
342300

343301
parsed.images = withoutMissing;

src/project.ts

-3
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,6 @@ export class Project extends MobileProject {
6262
iosIcon: await this.loadInputAsset('ios/icon', AssetKind.Icon, Platform.Ios),
6363
iosSplash: await this.loadInputAsset('ios/splash', AssetKind.Splash, Platform.Ios),
6464
iosSplashDark: await this.loadInputAsset('ios/splash-dark', AssetKind.SplashDark, Platform.Ios),
65-
iosNotificationIcon: await this.loadInputAsset('ios/notification-icon', AssetKind.NotificationIcon, Platform.Ios),
66-
iosSettingsIcon: await this.loadInputAsset('ios/settings-icon', AssetKind.SettingsIcon, Platform.Ios),
67-
iosSpotlightIcon: await this.loadInputAsset('ios/spotlight-icon', AssetKind.SpotlightIcon, Platform.Ios),
6865

6966
androidIcon: await this.loadInputAsset('android/icon', AssetKind.Icon, Platform.Android),
7067
androidIconForeground: await this.loadInputAsset('android/icon-foreground', AssetKind.Icon, Platform.Android),

test/asset.test.ts

-12
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,5 @@ describe('Asset test', () => {
4040
expect(assets.iosIcon?.format()).toBe(Format.Png);
4141
expect(assets.iosIcon?.width).toBe(1024);
4242
expect(assets.iosIcon?.height).toBe(1024);
43-
expect(assets.iosNotificationIcon).not.toBeNull();
44-
expect(assets.iosNotificationIcon?.format()).toBe(Format.Png);
45-
expect(assets.iosNotificationIcon?.width).toBe(1024);
46-
expect(assets.iosNotificationIcon?.height).toBe(1024);
47-
expect(assets.iosSettingsIcon).not.toBeNull();
48-
expect(assets.iosSettingsIcon?.format()).toBe(Format.Png);
49-
expect(assets.iosSettingsIcon?.width).toBe(1024);
50-
expect(assets.iosSettingsIcon?.height).toBe(1024);
51-
expect(assets.iosSpotlightIcon).not.toBeNull();
52-
expect(assets.iosSpotlightIcon?.format()).toBe(Format.Png);
53-
expect(assets.iosSpotlightIcon?.width).toBe(1024);
54-
expect(assets.iosSpotlightIcon?.height).toBe(1024);
5543
});
5644
});

test/fixtures/app-logo-only/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json

+3-105
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,10 @@
11
{
22
"images": [
33
{
4-
"size": "20x20",
5-
"idiom": "iphone",
6-
"filename": "[email protected]",
7-
"scale": "2x"
8-
},
9-
{
10-
"size": "20x20",
11-
"idiom": "iphone",
12-
"filename": "[email protected]",
13-
"scale": "3x"
14-
},
15-
{
16-
"size": "29x29",
17-
"idiom": "iphone",
18-
"filename": "[email protected]",
19-
"scale": "2x"
20-
},
21-
{
22-
"size": "29x29",
23-
"idiom": "iphone",
24-
"filename": "[email protected]",
25-
"scale": "3x"
26-
},
27-
{
28-
"size": "40x40",
29-
"idiom": "iphone",
30-
"filename": "[email protected]",
31-
"scale": "2x"
32-
},
33-
{
34-
"size": "40x40",
35-
"idiom": "iphone",
36-
"filename": "[email protected]",
37-
"scale": "3x"
38-
},
39-
{
40-
"size": "60x60",
41-
"idiom": "iphone",
42-
"filename": "[email protected]",
43-
"scale": "2x"
44-
},
45-
{
46-
"size": "60x60",
47-
"idiom": "iphone",
48-
"filename": "[email protected]",
49-
"scale": "3x"
50-
},
51-
{
52-
"size": "20x20",
53-
"idiom": "ipad",
54-
"filename": "[email protected]",
55-
"scale": "1x"
56-
},
57-
{
58-
"size": "20x20",
59-
"idiom": "ipad",
60-
"filename": "[email protected]",
61-
"scale": "2x"
62-
},
63-
{
64-
"size": "29x29",
65-
"idiom": "ipad",
66-
"filename": "[email protected]",
67-
"scale": "1x"
68-
},
69-
{
70-
"size": "29x29",
71-
"idiom": "ipad",
72-
"filename": "[email protected]",
73-
"scale": "2x"
74-
},
75-
{
76-
"size": "40x40",
77-
"idiom": "ipad",
78-
"filename": "[email protected]",
79-
"scale": "1x"
80-
},
81-
{
82-
"size": "40x40",
83-
"idiom": "ipad",
84-
"filename": "[email protected]",
85-
"scale": "2x"
86-
},
87-
{
88-
"size": "76x76",
89-
"idiom": "ipad",
90-
"filename": "[email protected]",
91-
"scale": "1x"
92-
},
93-
{
94-
"size": "76x76",
95-
"idiom": "ipad",
96-
"filename": "[email protected]",
97-
"scale": "2x"
98-
},
99-
{
100-
"size": "83.5x83.5",
101-
"idiom": "ipad",
102-
"filename": "[email protected]",
103-
"scale": "2x"
104-
},
105-
{
106-
"size": "1024x1024",
107-
"idiom": "ios-marketing",
1084
"filename": "[email protected]",
109-
"scale": "1x"
5+
"idiom": "universal",
6+
"platform": "ios",
7+
"size": "1024x1024"
1108
}
1119
],
11210
"info": {

0 commit comments

Comments
 (0)