unoplatform / uno

Build Mobile, Desktop and WebAssembly apps with C# and XAML. Today. Open source and professionally supported.
https://platform.uno
Apache License 2.0
8.78k stars 706 forks source link

Implement Theme Asset Qualifier #2197

Open pdecostervgls opened 4 years ago

pdecostervgls commented 4 years ago

What would you like to be added:

The theme qualifier for assets.

Why is this needed:

So images can be different depending on the theme.

For which Platform:

Anything else we need to know?

As outlined in: https://docs.microsoft.com/en-us/windows/uwp/app-resources/images-tailored-for-scale-theme-contrast

jeromelaban commented 4 years ago

Thanks for the report!

pdecostervgls commented 4 years ago

@jeromelaban You're welcome, could you assign it to me?, since I am planning om picking this up as soon as possible, since I'm working on dark mode support for my app.

pdecostervgls commented 4 years ago

I'm having trouble on finding out where to start on this. I found https://github.com/unoplatform/uno/blob/f3d6bb85913bbf9ecf573861e04029531d9623fb/src/SourceGenerators/Uno.UI.Tasks/Assets/RetargetAssets.cs but I cannot get the logs to show up. @ghuntley could you help me get started on this?

GitHub
unoplatform/uno
Build Mobile, Desktop and WebAssembly apps with C# and XAML. Today. Open source and professionally supported. - unoplatform/uno
MartinZikmund commented 4 years ago

@pdecostervgls The linked source code is just a build task, which makes sure the platform-specific assets get copied to the respective platforms during build. To achieve the theme qualifiers, there will be two components of the problem.

First you need to find out how (and if even) the theme-XYZ qualifier is copied to the build output folder on Android/iOS/WASM in some form. I guess that the qualifier might be omitted from the file name on Android and iOS and copied as-is on WASM at the moment. This will mean you will have to modify the RetargetAssets task to keep the qualifier in the file name or copy the assets to appropriate folders (in case of Android there is definitely a Resources/drawable-??? qualifier for dark/light theme, for example).

The second part of the task will be to implement correct asset resolution on the target platforms. This might be quite easy on Android, as it could be handled automatically for you by the OS, but on iOS and WASM it might require additional work.

pdecostervgls commented 4 years ago

@MartinZikmund I have verified that assets with the theme qualifier do already get copied to the build output folder, so I guess only the asset resolution part is left. I could look at how the scale assets get resolved and work from there?

MartinZikmund commented 4 years ago

That sounds good! Let me know when you encounter something :-)

pdecostervgls commented 4 years ago

I cannot find it. I'm starting to suspect that the asset resolving is actually implemented in Xamarin instead.

jeromelaban commented 4 years ago

Assets resolving for iOS and Android is done by the platform, given the proper naming convention.

The assets retargeting is done on Android by the AndroidResourcesConverter , called from the RetargetAssets task:

https://github.com/unoplatform/uno/blob/1ec834bb23d28161e110344849095b4761beea24/src/SourceGenerators/Uno.UI.Tasks/Assets/RetargetAssets.cs#L51-L62

Adding dark theme support would probably be similar to the support for multiple DPIs.

pdecostervgls commented 4 years ago

@jeromelaban I though that on iOS you had to create an assets catalog with the corresponding contents.json file to declare the DPIs. Other than retargeting the assets I cannot find anything creating a contents.json manifest for iOS.

jeromelaban commented 4 years ago

@pdecostervgls that's used for assets catalogs, not for bundle resources. But that may work differently for dark theme, there probably documentation on that.

pdecostervgls commented 4 years ago

@jeromelaban As far is I can find in the documentation, you cannot signify bundle resources for dark/light mode without wrapping them in a asset catalog. So I think we have to generate Image Sets for each asset. We could still use the Retargeting entrypoint for this, just some extra work.

jeromelaban commented 4 years ago

For iOS, that would make sense. Have you looked it up for Android as well ?

pdecostervgls commented 4 years ago

According to https://medium.com/androiddevelopers/appcompat-v23-2-daynight-d10f90c83e94 it supports the (renamed) asset qualifer, I can use the retargetassets for that too.

Medium
DayNight — Adding a dark theme to your app
The DayNight functionality in AppCompat allows your app to easily switch between a dark and light theme.
pdecostervgls commented 4 years ago

Come to think of it, I dont know for sure that the Image resolver will actually reference the xcassets entries that I plan on generating. Since the actual files do get retargetted as expected, wouldn't it be wiser to just override the Image Source resolver to try to match the image with the most fitting qualifiers at runtime? @jeromelaban @MartinZikmund

jeromelaban commented 4 years ago

@pdecostervgls for iOS, it's possible to generate the proper files and add them as ItemGroups so that the iOS tooling picks those up.

For the other platforms, and Wasm specifically, we'll have to handle that at runtime in all cases.

pdecostervgls commented 4 years ago

@MartinZikmund I unassigned myself because I lack the experience with VS ResourceGeneration to complete this. Would you like to pick it up? I got some work done (UI tests and set-up) at this branch

pdecostervgls commented 3 years ago

Is this closed because it is implemented? If so, i'd like to see the code, for education purposes :)

jeromelaban commented 3 years ago

It's not, it was closed incorrectly. Sorry about that :)

hawkerm commented 1 year ago

Ah, I just hit this with WASM trying to use an asset like Square150x150Logo.theme-light_scale-100.png and referencing in an image directly:

<Image Width="150"
             Height="150"
             Source="ms-appx:///Assets/Square150x150Logo.png" />

Saw there's a workaround that Labs did using ThemeDictionaries, see here: https://github.com/CommunityToolkit/Labs-Windows/blob/3669d4c52eafb2bcb9b1d782d85c1a49111e175f/common/CommunityToolkit.Labs.Shared/Pages/GettingStartedPage.xaml

GitHub
Labs-Windows/GettingStartedPage.xaml at 3669d4c52eafb2bcb9b1d782d85c1a49111e175f · CommunityToolkit/Labs-Windows
A safe space to collaborate and engineer solutions from the prototyping stage all the way through polished finalized component for the Windows Community Toolkit. - Labs-Windows/GettingStartedPage.x...
jeromelaban commented 1 year ago

That's correct. At this time, Wasm only supports assets scaling, and a theme resources workaround is the best way.