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

feat(icons)!: Support a single 1024⨉1024 icon, but also more complex customizations #1465

Merged
merged 3 commits into from
Aug 21, 2024

Conversation

dpogue
Copy link
Member

@dpogue dpogue commented Aug 17, 2024

Platforms affected

iOS (watchOS, and macOS Catalyst technically)

Motivation and Context

Xcode now supports generating all the app icons sizes automatically from a single 1024⨉1024 PNG image. Supporting this drastically simplifies the requirements for app developers.

That said, there are cases where an app developer might want to provide specific icons for specific situations (such as watchOS notifications, or a macOS Catalyst app) and historically Cordova has been pretty bad at supporting those customizations due to relying solely on image sizes to handle mappings.

iOS 18 is also introducing dark mode and tinted app icon variants, and we need a way to support those.

Description

Simple case

For the simplest case, an app developer can provide a single 1024⨉1024 icon image and list it in their config.xml file with no attributes:

<platform name="ios">
    <icon src="appicon.png" />
</platform>

With iOS 18 variants

We make use of the foreground and monochrome attributes, already supported in Cordova Android, to handle the dark mode and tint-able icon variants.

The dark mode icon should have a transparent background (hence, the foreground attribute).
The tint-able icon should be a greyscale mask that gets multiplied by the system tint colour (hence, the monochrome attribute).

Example images:
sampleicon sampleicon-dark sampleicon-tint

Example config:

<platform name="ios">
    <icon src="appicon.png" foreground="appicon-dark.png" monochrome="appicon-tint.png" />
</platform>

You can provide variants for all iOS icons (but variants are not supported on watchOS or macOS Catalyst).

Platform-specific icons

Apple watchOS supports the same automatic generation of icons from a single 1024⨉1024 icon. By default this will use the app icon, but it can be overridden by providing another icon with a target attribute.

<platform name="ios">
    <icon src="appicon.png" />
    <icon src="watchicon.png" target="watchos" />
</platform>

Supported targets are watchos and mac. There's a special case target spotlight for iOS to disambiguate some icons that otherwise have identical sizes (only applicable if you are providing all your own icon sizes).

The macOS icons do not support a single 1024⨉1024 image, so if you want to customize those then you will need to provide all the required icon sizes yourself.

Providing all the icon sizes

If you prefer to provide all the icons yourself, you can still do so. Note that if you provide any sized icons, you are required to provide all the sized icons for that platform.

<platform name="ios">
    <icon src="appicon-40.png" width="40" height="40" />
    <icon src="appicon-58.png" width="58" height="58" />
    <icon src="appicon-60.png" width="60" height="60" />
    <icon src="appicon-72.png" width="72" height="72" />
    <icon src="appicon-80.png" width="80" height="80" target="spotlight" />
    <icon src="appicon-87.png" width="87" height="87" />
    <icon src="appicon-120.png" width="120" height="120" />
    <icon src="appicon-120.png" width="120" height="120" target="spotlight" />
    <icon src="appicon-128.png" width="128" height="128" />
    <icon src="appicon-136.png" width="136" height="136" />
    <icon src="appicon-144.png" width="144" height="144" />
    <icon src="appicon-152.png" width="152" height="152" />
    <icon src="appicon-167.png" width="167" height="167" />
    <icon src="appicon-180.png" width="180" height="180" />
    <icon src="appicon-196.png" width="196" height="196" />
    <icon src="appicon-1024.png" width="1024" height="1024" />
</platform>

You can also provide all the icons for the watchos and mac targets, with all their respective sizes.

Testing

  • Existing unit tests pass
  • New unit tests written to provide code coverage of icon mapping changes
  • Testing in a real project with simple icon mapping
  • Tested in a real project with complex icon mapping

Closed issues

Closes #592.
Closes #623.
Closes #657.
Closes #658.
Closes #1019.
Closes #1233.
Closes #1387.
Closes #1462.

Checklist

  • I've run the tests to see all new and existing tests pass
  • I added automated test coverage as appropriate for this change
  • If this Pull Request resolves an issue, I linked to the issue in the text above (and used the correct keyword to close issues using keywords)
  • I've updated the documentation if necessary

@dpogue dpogue added this to the 8.0.0 milestone Aug 17, 2024
@codecov-commenter
Copy link

codecov-commenter commented Aug 17, 2024

Codecov Report

Attention: Patch coverage is 90.90909% with 7 lines in your changes missing coverage. Please review.

Project coverage is 80.22%. Comparing base (3a426fd) to head (d63d690).

Files Patch % Lines
lib/prepare.js 90.90% 7 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1465      +/-   ##
==========================================
+ Coverage   78.31%   80.22%   +1.91%     
==========================================
  Files          16       16              
  Lines        1826     1871      +45     
==========================================
+ Hits         1430     1501      +71     
+ Misses        396      370      -26     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@dpogue dpogue force-pushed the refactor5-icons branch 2 times, most recently from 8fc533d to 3ea57bf Compare August 18, 2024 08:05
@dpogue dpogue changed the title WIP: feat(icons)!: Support a single 1024⨉1024 icon, but also more complex customizations feat(icons)!: Support a single 1024⨉1024 icon, but also more complex customizations Aug 18, 2024
@dpogue dpogue marked this pull request as ready for review August 18, 2024 08:30
@dpogue dpogue force-pushed the refactor5-icons branch 2 times, most recently from 8a04ef6 to 168eb8b Compare August 20, 2024 08:09
@dpogue
Copy link
Member Author

dpogue commented Aug 20, 2024

We've got one issue to sort out here, and it's related to the new iOS 18 icon variants and Xcode support.

Icon variants are only supported/understood by Xcode 16. If you set up icon variants, and then open the project in Xcode 15 (or lower) it will see 3 icons trying to fill the same slot and pick one at random (and almost always one of the variants instead of the default icon). I already tried reordering the icons in Contents.json and that did not produce consistent behaviour 😞

One option (and the easiest) is to document this behaviour and say that specifying icon variants only works with Xcode 16 and up. Documentation gives us something to point to when people open issues about it, but I have low confidence in its ability to prevent issues from being opened.

The second option (and what I tried to do here) is to detect the Xcode version at prepare-time and only add the icon variants if it's 16 or higher. This works great on macOS. However, we support adding and preparing the iOS platform on other OSes where Xcode is not present, and that prepare-time check is failing. So the question here is what to do about those other platforms, do we make them pretend to be Xcode 15 (and skip the variants) or Xcode 16 (and potentially include broken variants)?

Would be good to get some feedback or other proposals for how best to handle this @jcesarmobile @breautek @erisu

jcesarmobile and others added 2 commits August 20, 2024 18:59
Ironically, this also allows most people to drastically simplify their
icons by only providing a single 1024⨉1024 image with no special
attributes.

Closes apacheGH-592.
Closes apacheGH-623.
Closes apacheGH-657.
Closes apacheGH-658.
Closes apacheGH-1019.
Closes apacheGH-1233.
Closes apacheGH-1387.
@erisu
Copy link
Member

erisu commented Aug 21, 2024

I would go with the second option.

As for anyone who runs the cordova prepare command on a non-macOS (Darwin) platform, I would suggest it skips the variants setup and behave as if it was Xcode 15.

As of right now, building an app with Xcode 16 is not a hard requirement of the App Store and I believe it wont be until April 2025. Once it becomes a hard requirement, then we can remove the version check and default the variants setup for all systems.

Xcode 15 doesn't understand the appearance variants, and if variants are
specified then it thinks there are 3 images assigned to the same slot
and ends up picking one at random and we don't want that.
Copy link
Member

@erisu erisu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code changes LGTM

I tested and confirmed that:

  • Xcode 16 Beta 5 will generate entries for dark and tinted icons in Assets.xcassets/AppIcon.appiconset/Contents.json when the icon's foreground and monochrome properties are defined in config.xml.
  • Xcode 16 Beta 5 will NOT generate entries for dark and tinted icons in Assets.xcassets/AppIcon.appiconset/Contents.json when the icon does NOT define a foreground and monochrome properties in config.xml.
  • Xcode 16 Beta 5 will NOT generate entries for dark icon in Assets.xcassets/AppIcon.appiconset/Contents.json when the icon's foreground property is NOT defined in config.xml.
  • Xcode 16 Beta 5 will NOT generate entries for tinted icon in Assets.xcassets/AppIcon.appiconset/Contents.json when the icon's monochrome property is NOT defined in config.xml.
  • Xcode 15.4 will NOT generate entries for dark and tinted icons in Assets.xcassets/AppIcon.appiconset/Contents.json when the icon's foreground and monochrome properties are defined in config.xml.

@dpogue dpogue merged commit 3ce3a7e into apache:master Aug 21, 2024
10 checks passed
@dpogue dpogue deleted the refactor5-icons branch August 21, 2024 07:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment