From 4a3cce712a3d55b38db5c2033cc6b9f8081bed70 Mon Sep 17 00:00:00 2001 From: Jerome Laban Date: Fri, 14 Oct 2022 09:07:14 -0400 Subject: [PATCH 1/3] feat(assets): Adds support for content assets in NuGet and transive project refs --- build/Uno.UI.Build.csproj | 2 +- build/Uno.WinUI.nuspec | 20 +- .../run-net6-mobile-template-tests.ps1 | 24 +++ build/test-scripts/run-template-tests.ps1 | 5 - doc/articles/features/file-management.md | 11 +- doc/articles/get-started-vs-2022.md | 3 + .../guides/how-to-create-control-libraries.md | 21 +++ .../SamplesApp.Skia.Gtk.csproj | 13 ++ .../SamplesApp.iOS/SamplesApp.iOS.csproj | 4 +- .../Uno.ProjectTemplates.Dotnet.csproj | 16 +- .../CrossTargetedLibrary.csproj | 13 +- .../UnoSolutionTemplate.Wizard.2022.csproj | 4 +- .../Assets/ExpandPackageAssets.cs | 67 +++++++ .../Uno.UI.Tasks/Assets/RetargetAssets.cs | 14 +- .../Uno.UI.Tasks/Content/Uno.UI.Tasks.targets | 15 +- .../Content/uno.ui.tasks.assets.targets | 171 ++++++++++++++++++ .../Assets/TransientAsset01.txt | 1 + .../Assets/Transitive-ingredient01.png | Bin 0 -> 5266 bytes .../Windows_Storage/Given_StorageFile.cs | 28 ++- .../Windows_UI_Xaml_Controls/Given_Image.cs | 16 ++ .../Uno.UI.RuntimeTests.Skia.csproj | 14 ++ .../Uno.UI.RuntimeTests.Wasm.csproj | 3 +- .../Uno.UI.RuntimeTests.csproj | 4 +- .../Uno.UI.RuntimeTests.net6.csproj | 4 +- .../UI/Xaml/Media/ImageSource.Android.cs | 6 + .../UI/Xaml/Media/ImageSource.iOSmacOS.cs | 5 + src/Uno.UI/UI/Xaml/Media/ImageSource.wasm.cs | 9 +- .../UI/Xaml/Media/Imaging/BitmapImage.skia.cs | 6 + src/Uno.UI/Uno.UI.Wasm.csproj | 20 +- src/Uno.UWP/Storage/StorageFile.Android.cs | 9 +- src/Uno.UWP/Storage/StorageFile.iOSmacOS.cs | 5 + src/Uno.UWP/Storage/StorageFile.skia.cs | 2 +- src/Uno.UWP/Storage/StorageFile.wasm.cs | 5 + 33 files changed, 483 insertions(+), 57 deletions(-) create mode 100644 src/SourceGenerators/Uno.UI.Tasks/Assets/ExpandPackageAssets.cs create mode 100644 src/SourceGenerators/Uno.UI.Tasks/Content/uno.ui.tasks.assets.targets create mode 100644 src/Uno.UI.RuntimeTests/Assets/TransientAsset01.txt create mode 100644 src/Uno.UI.RuntimeTests/Assets/Transitive-ingredient01.png diff --git a/build/Uno.UI.Build.csproj b/build/Uno.UI.Build.csproj index f13061fb792b..e8752d04360b 100644 --- a/build/Uno.UI.Build.csproj +++ b/build/Uno.UI.Build.csproj @@ -201,7 +201,7 @@ <_Sha1Replace Include="..\src\SourceGenerators\Uno.UI.Tasks\**\*.cs" /> <_Sha1Replace Include="..\src\SourceGenerators\Uno.UI.Tasks\Uno.UI.Tasks.csproj" /> - <_Sha1Replace Include="..\src\SourceGenerators\Uno.UI.Tasks\Content\Uno.UI.Tasks.targets" /> + <_Sha1Replace Include="..\src\SourceGenerators\Uno.UI.Tasks\Content\Uno.UI.Tasks*.*" /> - - - - - - - - - - + + + + + + + + + + diff --git a/build/test-scripts/run-net6-mobile-template-tests.ps1 b/build/test-scripts/run-net6-mobile-template-tests.ps1 index bef06d347739..53dfe51c07db 100644 --- a/build/test-scripts/run-net6-mobile-template-tests.ps1 +++ b/build/test-scripts/run-net6-mobile-template-tests.ps1 @@ -96,3 +96,27 @@ Assert-ExitCodeIsZero & dotnet build -c Debug MyAppXamlTrim\MyAppXamlTrim.Wasm\MyAppXamlTrim.Wasm.csproj /p:UnoXamlResourcesTrimming=true Assert-ExitCodeIsZero + +# Uno Library +dotnet new unolib -n MyUnoLib +& $msbuild $debug /t:pack MyUnoLib\MyUnoLib.csproj +Assert-ExitCodeIsZero + +# +# Uno Library with assets, Validate assets count +# +dotnet new unolib -n MyUnoLib2 +mkdir MyUnoLib2\Assets +echo "Test file" > MyUnoLib2\Assets\MyTestAsset01.txt +& $msbuild $debug /t:pack /p:IncludeContentInPack=false MyUnoLib2\MyUnoLib2.csproj -bl +Assert-ExitCodeIsZero + +mv MyUnoLib2\Bin\Debug\MyUnoLib2.1.0.0.nupkg MyUnoLib2\Bin\Debug\MyUnoLib2.1.0.0.zip +Expand-Archive -LiteralPath MyUnoLib2\Bin\Debug\MyUnoLib2.1.0.0.zip -DestinationPath MyUnoLib2Extract + +$assetsCount = Get-ChildItem MyUnoLib2Extract\ -Filter MyTestAsset01.txt -Recurse -File | Measure-Object | %{$_.Count} + +if ($assetsCount -ne 6) +{ + throw "Not enough assets in the package." +} diff --git a/build/test-scripts/run-template-tests.ps1 b/build/test-scripts/run-template-tests.ps1 index 58d8b58cd8b3..1ece44bc56c0 100644 --- a/build/test-scripts/run-template-tests.ps1 +++ b/build/test-scripts/run-template-tests.ps1 @@ -103,11 +103,6 @@ dotnet new unoapp-uwp -n MyApp.Android (Get-TemplateConfiguration -android 1) & $msbuild $debug MyApp.Android\MyApp.Android.sln Assert-ExitCodeIsZero -# Uno Library -dotnet new unolib -n MyUnoLib -& $msbuild $debug /t:Pack MyUnoLib\MyUnoLib.csproj -Assert-ExitCodeIsZero - # Uno Cross-Runtime Library dotnet new unolib-crossruntime -n MyCrossRuntimeLib & $msbuild $debug /t:Pack MyCrossRuntimeLib\MyCrossRuntimeLib.sln diff --git a/doc/articles/features/file-management.md b/doc/articles/features/file-management.md index cc989b3a16bc..1fb7523322e0 100644 --- a/doc/articles/features/file-management.md +++ b/doc/articles/features/file-management.md @@ -49,7 +49,7 @@ Note that you can view the content of the **IndexedDB** in the Application tab o ## Support for `StorageFile.GetFileFromApplicationUriAsync` -Uno supports the ability to get package files using the [`StorageFile.GetFileFromApplicationUriAsync`](https://docs.microsoft.com/en-us/uwp/api/windows.storage.storagefile.getfilefromapplicationuriasync). +Uno Platform supports the ability to get package files using the [`StorageFile.GetFileFromApplicationUriAsync`](https://docs.microsoft.com/en-us/uwp/api/windows.storage.storagefile.getfilefromapplicationuriasync). Support per platform may vary: - On non-WebAssembly targets, the file is available directly as it is a part of the installed package. @@ -68,6 +68,15 @@ Given than in the project there's the following declaration: ``` +### Support for Library provided assets +Since Uno Platform 4.6, the `GetFileFromApplicationUriAsync` method supports reading assets provided by `ProjectReference` or `PackageReference` libraries, using the following syntax: + +Given a library or package named `MyLibray01`, the following can be used to read assets: +```csharp +var file = await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx://MyLibray01/MyPackageFile.xml")); +var content = await FileIO.ReadTextAsync(file); +``` + ## Support for `RandomAccessStreamReference.CreateFromUri` Uno Platform supports the creation of a `RandomAccessStreamReference` from an `Uri` (`RandomAccessStreamReference.CreateFromUri`), but note that on WASM downloading a file from a server often causes issues with [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). diff --git a/doc/articles/get-started-vs-2022.md b/doc/articles/get-started-vs-2022.md index 1d745ee3b23d..a8d12ade8f85 100644 --- a/doc/articles/get-started-vs-2022.md +++ b/doc/articles/get-started-vs-2022.md @@ -66,6 +66,9 @@ To create an Uno Platform app: 1. To run the **WebAssembly** (Wasm) head: - Right click on the `MyApp.Wasm` project, select **Set as startup project** - Press the `MyApp.Wasm` button to deploy the app +1. To run the ASP.NET Hosted **WebAssembly** (Server) head: + - Right click on the `MyApp.Server` project, select **Set as startup project** + - Press the `MyApp.Server` button to deploy the app 1. To debug for **iOS**: - Right click on the `MyApp.Mobile` project, select **Set as startup project** - In the "Debug toolbar" drop down, select framework `net6.0-ios`: diff --git a/doc/articles/guides/how-to-create-control-libraries.md b/doc/articles/guides/how-to-create-control-libraries.md index 137689d691e2..194c68c79b39 100644 --- a/doc/articles/guides/how-to-create-control-libraries.md +++ b/doc/articles/guides/how-to-create-control-libraries.md @@ -54,3 +54,24 @@ You can find the [full sample code](https://github.com/unoplatform/Uno.Samples/b ```xml ``` + +## Library assets + +WinUI 3 and Uno Platform (4.6 and later) Libraries support the inclusion of content assets to be used with [`StorageFile.GetFileFromApplicationUriAsync`](../features/file-management.md#support-for-storagefilegetfilefromapplicationuriasync), as well as with the `ms-appx://[libraryname]/[assetname_file_name]` format. + +Library assets can be of any type. + +Library assets are supported in two configurations: +- `ProjectReference`, where the library project is included in the solution with the application that uses it +- `PackageReference`, where the library project is being packaged as a NuGet package, and used in a separate solution, from a NuGet feed. + +In both cases, for the build system to include the assets files, the following property must be set in the library's `.csproj`: + +```xml + + true + +``` + +> [!IMPORTANT] +> WinAppSDK [does not support assets](https://github.com/microsoft/microsoft-ui-xaml/issues/6429) if the application is using the MSIX package mode. To use the unpackaged mode, [see this article](../features/winapp-sdk-specifics.md#unpackaged-application-support). diff --git a/src/SamplesApp/SamplesApp.Skia.Gtk/SamplesApp.Skia.Gtk.csproj b/src/SamplesApp/SamplesApp.Skia.Gtk/SamplesApp.Skia.Gtk.csproj index 82e1023e1db0..31ba968c7992 100644 --- a/src/SamplesApp/SamplesApp.Skia.Gtk/SamplesApp.Skia.Gtk.csproj +++ b/src/SamplesApp/SamplesApp.Skia.Gtk/SamplesApp.Skia.Gtk.csproj @@ -52,8 +52,21 @@ + + $(MSBuildThisFileDirectory)..\..\SourceGenerators\Uno.UI.Tasks\bin\$(Configuration)_Shadow + + + + + + + + + diff --git a/src/SamplesApp/SamplesApp.iOS/SamplesApp.iOS.csproj b/src/SamplesApp/SamplesApp.iOS/SamplesApp.iOS.csproj index 9824e322c04d..9e06950ff5fc 100644 --- a/src/SamplesApp/SamplesApp.iOS/SamplesApp.iOS.csproj +++ b/src/SamplesApp/SamplesApp.iOS/SamplesApp.iOS.csproj @@ -105,12 +105,12 @@ - + - + PreserveNewest diff --git a/src/SolutionTemplate/Uno.ProjectTemplates.Dotnet/Uno.ProjectTemplates.Dotnet.csproj b/src/SolutionTemplate/Uno.ProjectTemplates.Dotnet/Uno.ProjectTemplates.Dotnet.csproj index b8787deac057..4888acf7a3a1 100644 --- a/src/SolutionTemplate/Uno.ProjectTemplates.Dotnet/Uno.ProjectTemplates.Dotnet.csproj +++ b/src/SolutionTemplate/Uno.ProjectTemplates.Dotnet/Uno.ProjectTemplates.Dotnet.csproj @@ -124,14 +124,14 @@ - <_UnoLibTemplateFilesExclude Include="..\UnoLibraryTemplate\*.vstemplate" /> - <_UnoLibTemplateFilesExclude Include="..\UnoLibraryTemplate\**\__*.png" /> - <_UnoLibTemplateFilesExclude Include="..\UnoLibraryTemplate\obj\**" /> - <_UnoLibTemplateFilesExclude Include="..\UnoLibraryTemplate\bin\**" /> - <_UnoLibTemplateFilesExclude Include="..\UnoLibraryTemplate\Properties\**" /> - <_UnoLibTemplateFilesExclude Include="..\UnoLibraryTemplate\UnoLibraryTemplate.csproj" /> - - <_UnoLibTemplateFiles Include="..\UnoLibraryTemplate\**" Exclude="@(_UnoLibTemplateFilesExclude)" /> + <_UnoLibTemplateFilesExclude Include="..\UnoLibraryTemplate.net6\*.vstemplate" /> + <_UnoLibTemplateFilesExclude Include="..\UnoLibraryTemplate.net6\**\__*.png" /> + <_UnoLibTemplateFilesExclude Include="..\UnoLibraryTemplate.net6\obj\**" /> + <_UnoLibTemplateFilesExclude Include="..\UnoLibraryTemplate.net6\bin\**" /> + <_UnoLibTemplateFilesExclude Include="..\UnoLibraryTemplate.net6\Properties\**" /> + <_UnoLibTemplateFilesExclude Include="..\UnoLibraryTemplate.net6\UnoLibraryTemplate.net6.csproj" /> + + <_UnoLibTemplateFiles Include="..\UnoLibraryTemplate.net6\**" Exclude="@(_UnoLibTemplateFilesExclude)" /> diff --git a/src/SolutionTemplate/UnoLibraryTemplate.net6/CrossTargetedLibrary.csproj b/src/SolutionTemplate/UnoLibraryTemplate.net6/CrossTargetedLibrary.csproj index a2c31d9560f2..c1d97a012a7d 100644 --- a/src/SolutionTemplate/UnoLibraryTemplate.net6/CrossTargetedLibrary.csproj +++ b/src/SolutionTemplate/UnoLibraryTemplate.net6/CrossTargetedLibrary.csproj @@ -6,18 +6,19 @@ true - - - - - + - + + + + + + %(Filename) diff --git a/src/SolutionTemplate/UnoSolutionTemplate.Wizard.2022/UnoSolutionTemplate.Wizard.2022.csproj b/src/SolutionTemplate/UnoSolutionTemplate.Wizard.2022/UnoSolutionTemplate.Wizard.2022.csproj index e12a9b33ed5a..38d6bb8c2e9e 100644 --- a/src/SolutionTemplate/UnoSolutionTemplate.Wizard.2022/UnoSolutionTemplate.Wizard.2022.csproj +++ b/src/SolutionTemplate/UnoSolutionTemplate.Wizard.2022/UnoSolutionTemplate.Wizard.2022.csproj @@ -56,7 +56,9 @@ UnoOptions.cs - + + Form + Form diff --git a/src/SourceGenerators/Uno.UI.Tasks/Assets/ExpandPackageAssets.cs b/src/SourceGenerators/Uno.UI.Tasks/Assets/ExpandPackageAssets.cs new file mode 100644 index 000000000000..0f621b698c01 --- /dev/null +++ b/src/SourceGenerators/Uno.UI.Tasks/Assets/ExpandPackageAssets.cs @@ -0,0 +1,67 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using System.IO; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace Uno.UI.Tasks.Assets +{ + /// + /// Expands content assets from folders containing an uprimarker file + /// + public class ExpandPackageAssets_v0 : Task + { + [Required] + public ITaskItem[]? MarkerFiles { get; set; } + + [Output] + public ITaskItem[]? Assets { get; set; } + = Array.Empty(); + + public override bool Execute() + { + Log.LogMessage($"Expanding package assets"); + + if (MarkerFiles != null) + { + List assets = new(); + + foreach (var markerFile in MarkerFiles) + { + var markerFileFullPath = markerFile.GetMetadata("FullPath"); + var markerFileDirectory = Path.GetDirectoryName(markerFileFullPath); + var basePath = Path.Combine(markerFileDirectory, Path.GetFileNameWithoutExtension(markerFileFullPath)); + + if (Directory.Exists(basePath)) + { + Log.LogMessage(MessageImportance.Low, $"Scanning directory ({basePath})"); + + var markerFileDirectoryForReplace = markerFileDirectory + Path.DirectorySeparatorChar; + + foreach (var asset in Directory.EnumerateFiles(basePath, "*.*", SearchOption.AllDirectories)) + { + var newItem = new TaskItem( + asset, + new Dictionary + { + ["TargetPath"] = asset.Replace(markerFileDirectoryForReplace, "") + }); + + assets.Add(newItem); + } + } + else + { + Log.LogMessage(MessageImportance.Low, $"No assets directory found ({basePath})"); + } + } + + Assets = assets.ToArray(); + } + + return true; + } + } +} diff --git a/src/SourceGenerators/Uno.UI.Tasks/Assets/RetargetAssets.cs b/src/SourceGenerators/Uno.UI.Tasks/Assets/RetargetAssets.cs index d710bd68e4f2..d8175399c7ac 100644 --- a/src/SourceGenerators/Uno.UI.Tasks/Assets/RetargetAssets.cs +++ b/src/SourceGenerators/Uno.UI.Tasks/Assets/RetargetAssets.cs @@ -75,21 +75,26 @@ private TaskItem ProcessContentItem(ITaskItem asset, Func().Contains("Link") + && !asset.MetadataNames.OfType().Contains("TargetPath") && !asset.MetadataNames.OfType().Contains("DefiningProjectDirectory") ) { - Log.LogMessage($"Skipping '{asset.ItemSpec}' because 'Link' or 'DefiningProjectDirectory' metadata is not set."); + Log.LogMessage($"Skipping '{asset.ItemSpec}' because 'Link', 'TargetPath' or 'DefiningProjectDirectory' metadata is not set."); return null; } var fullPath = asset.GetMetadata("FullPath"); - var relativePath = asset.GetMetadata("Link"); + var relativePath = asset.GetMetadata("Link") is { Length: > 0 } link + ? link + : asset.GetMetadata("TargetPath"); if (string.IsNullOrEmpty(relativePath)) { relativePath = fullPath.Replace(asset.GetMetadata("DefiningProjectDirectory"), ""); } + relativePath = AlignPath(relativePath); + if (IsImageAsset(asset.ItemSpec)) { var resourceCandidate = ResourceCandidate.Parse(fullPath, relativePath); @@ -138,5 +143,10 @@ private static bool IsImageAsset(string path) || extension == ".jpeg" || extension == ".gif"; } + + private static string AlignPath(string path) + => path + .Replace('/', Path.DirectorySeparatorChar) + .Replace('\\', Path.DirectorySeparatorChar); } } diff --git a/src/SourceGenerators/Uno.UI.Tasks/Content/Uno.UI.Tasks.targets b/src/SourceGenerators/Uno.UI.Tasks/Content/Uno.UI.Tasks.targets index 75ac669f8f24..3b6981a46737 100644 --- a/src/SourceGenerators/Uno.UI.Tasks/Content/Uno.UI.Tasks.targets +++ b/src/SourceGenerators/Uno.UI.Tasks/Content/Uno.UI.Tasks.targets @@ -9,6 +9,8 @@ + + @@ -52,9 +54,14 @@ + BeforeTargets="_GetLibraryImports;_CheckForContent;_CollectBundleResources" + DependsOnTargets="ResolveProjectReferences;GetCopyToOutputDirectoryItems" + Condition=" + '$(DesignTimeBuild)' != 'true' + and '$(BuildingInsideUnoSourceGenerator)' == '' + and ('$(IsUnoHead)'=='true' + or '$(AndroidApplication)'=='true' + or '$(ProjectTypeGuids)'!='')"> True @@ -62,7 +69,7 @@ + + + + + + + + $(TargetsForTfmSpecificContentInPackage);_UnoIncludeLibraryAssets + + $(AssemblyName.ToLowerInvariant()) + $(UnoPriInitialPath).uprimarker + $(TargetDir)$(ProjectUnoPriFileName) + + + + + + + + <_AllChildProjectItemsWithTargetPath Include="$(ProjectUnoPriFullPath)"> + $(ProjectUnoPriFileName) + PreserveNewest + + + + + + + + + + + + + + + + <_UnoTargetPlatformVersion + Condition=" + '$(TargetPlatformIdentifier)'=='android' + or '$(TargetPlatformIdentifier)'=='ios' + or '$(TargetPlatformIdentifier)'=='macos' + or '$(TargetPlatformIdentifier)'=='maccatalyst' + ">$(TargetPlatformVersion) + + + + <_filteredContentWithTargetPath + Include="@(ContentWithTargetPath)" /> + + + + + + + + + + + + + + + + + + + + + + <_AllChildProjectItemsWithTargetPath Include="@(_UnoAssetsFilesExpanded)" KeepMetadata="TargetPath"> + $(PriInitialPath)\%(_UnoAssetsFilesExpanded.TargetPath) + PreserveNewest + + + + + + + + <_UnoPriFiles Include="@(RuntimeCopyLocalItems->'%(RootDir)%(Directory)%(Filename).uprimarker')" + Condition="$([System.IO.File]::Exists('%(RootDir)%(Directory)%(Filename).uprimarker'))"/> + + + + + + + <_UnoAddAssetsFilesToCopyLocalDependsOn> + ContentFilesProjectOutputGroup; + AssignTargetPaths; + _DefineUnoPriProperties; + $(_UnoAddAssetsFilesToCopyLocalDependsOn) + + + + + + + + <_AllChildProjectItemsWithTargetPath Include="@(ContentFilesProjectOutputGroupOutput)"> + $(UnoPriInitialPath)\%(ContentFilesProjectOutputGroupOutput.TargetPath) + PreserveNewest + + + + + + + + + + + + + + diff --git a/src/Uno.UI.RuntimeTests/Assets/TransientAsset01.txt b/src/Uno.UI.RuntimeTests/Assets/TransientAsset01.txt new file mode 100644 index 000000000000..2b65cf220209 --- /dev/null +++ b/src/Uno.UI.RuntimeTests/Assets/TransientAsset01.txt @@ -0,0 +1 @@ +My Transient Asset 01 diff --git a/src/Uno.UI.RuntimeTests/Assets/Transitive-ingredient01.png b/src/Uno.UI.RuntimeTests/Assets/Transitive-ingredient01.png new file mode 100644 index 0000000000000000000000000000000000000000..58a048212bad1c1204f2344fa04b454adc50d1ba GIT binary patch literal 5266 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 Path.Combine(ApplicationData.Current.LocalFolder.Path, $"{Guid.NewGuid()}.txt"); diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_Image.cs b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_Image.cs index 8711b929eda3..b0fee488aa2d 100644 --- a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_Image.cs +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_Image.cs @@ -133,6 +133,22 @@ public void TargetNullValue_Is_Correctly_Applied() Assert.AreEqual("ms-appx:///Assets/StoreLogo.png", targetNullValueSource.UriSource.ToString()); } + [TestMethod] + [RunsOnUIThread] + public async Task When_Transitive_Asset_Loaded() + { + string url = "ms-appx://Uno.UI.RuntimeTests/Assets/Transitive-ingredient01.png"; + var img = new Image(); + var SUT = new BitmapImage(new Uri(url)); + img.Source = SUT; + + TestServices.WindowHelper.WindowContent = img; + await TestServices.WindowHelper.WaitForIdle(); + await TestServices.WindowHelper.WaitFor(() => img.ActualHeight > 0, 3000); + + Assert.IsTrue(img.ActualHeight > 0); + } + [TestMethod] [RunsOnUIThread] public async Task When_Image_Is_Loaded_From_URL() diff --git a/src/Uno.UI.RuntimeTests/Uno.UI.RuntimeTests.Skia.csproj b/src/Uno.UI.RuntimeTests/Uno.UI.RuntimeTests.Skia.csproj index 81a73a09e1dd..97b47c6c62f1 100644 --- a/src/Uno.UI.RuntimeTests/Uno.UI.RuntimeTests.Skia.csproj +++ b/src/Uno.UI.RuntimeTests/Uno.UI.RuntimeTests.Skia.csproj @@ -18,6 +18,9 @@ Skia .\ $(DefineConstants);IS_RUNTIME_UI_TESTS + + + true <_UnoEmbeddedResourcesInjectionAfterTargets Include="CompileTypeScriptWithTSConfig" /> @@ -183,11 +194,6 @@ - - - - - diff --git a/src/Uno.UWP/Storage/StorageFile.Android.cs b/src/Uno.UWP/Storage/StorageFile.Android.cs index 397e12670289..a47c66985d2d 100644 --- a/src/Uno.UWP/Storage/StorageFile.Android.cs +++ b/src/Uno.UWP/Storage/StorageFile.Android.cs @@ -29,7 +29,14 @@ private static async Task GetFileFromApplicationUri(CancellationTok throw new InvalidOperationException("Uri is not using the ms-appx scheme"); } - var path = AndroidResourceNameEncoder.EncodeResourcePath(Uri.UnescapeDataString(uri.PathAndQuery).TrimStart(new char[] { '/' })); + var originalPath = Uri.UnescapeDataString(uri.PathAndQuery).TrimStart(new char[] { '/' }); + + if (uri.Host is { Length: > 0 } host) + { + originalPath = host.ToLowerInvariant() + "/" + originalPath.TrimStart('/'); + } + + var path = AndroidResourceNameEncoder.EncodeResourcePath(originalPath); // Read the contents of our asset var outputCachePath = global::System.IO.Path.Combine(Android.App.Application.Context.CacheDir.AbsolutePath, path); diff --git a/src/Uno.UWP/Storage/StorageFile.iOSmacOS.cs b/src/Uno.UWP/Storage/StorageFile.iOSmacOS.cs index 5b0831990174..40d8a4717934 100644 --- a/src/Uno.UWP/Storage/StorageFile.iOSmacOS.cs +++ b/src/Uno.UWP/Storage/StorageFile.iOSmacOS.cs @@ -25,6 +25,11 @@ private static async Task GetFileFromApplicationUri(CancellationTok if (directoryName != null) { + if (uri.Host is { Length: > 0 } host) + { + directoryName = host.ToLowerInvariant() + "/" + directoryName.TrimStart('/'); + } + var resourcePathname = NSBundle.MainBundle.PathForResource(global::System.IO.Path.Combine(directoryName, fileName), fileExtension.Substring(1)); if (resourcePathname != null) diff --git a/src/Uno.UWP/Storage/StorageFile.skia.cs b/src/Uno.UWP/Storage/StorageFile.skia.cs index 12fcff76ebe4..160230d86bad 100644 --- a/src/Uno.UWP/Storage/StorageFile.skia.cs +++ b/src/Uno.UWP/Storage/StorageFile.skia.cs @@ -19,7 +19,7 @@ private static async Task GetFileFromApplicationUri(CancellationTok var path = Uri.UnescapeDataString(uri.PathAndQuery).TrimStart(new char[] { '/' }); - var resourcePathname = global::System.IO.Path.Combine(Package.Current.InstalledLocation.Path, path); + var resourcePathname = global::System.IO.Path.Combine(Package.Current.InstalledLocation.Path, uri.Host.ToLowerInvariant(), path); if (resourcePathname != null) { diff --git a/src/Uno.UWP/Storage/StorageFile.wasm.cs b/src/Uno.UWP/Storage/StorageFile.wasm.cs index dfa1a17ffce7..f41e14a41aef 100644 --- a/src/Uno.UWP/Storage/StorageFile.wasm.cs +++ b/src/Uno.UWP/Storage/StorageFile.wasm.cs @@ -22,6 +22,11 @@ private static async Task GetFileFromApplicationUri(CancellationTok var path = Uri.UnescapeDataString(uri.PathAndQuery); + if(uri.Host is { Length: > 0 } host) + { + path = host + "/" + path.TrimStart("/"); + } + return await StorageFile.GetFileFromPathAsync(await AssetsManager.DownloadAsset(ct, path)); } } From b8758add08b2304a712e4c006bd3eb7b52f2b756 Mon Sep 17 00:00:00 2001 From: Jerome Laban Date: Thu, 20 Oct 2022 11:50:45 -0400 Subject: [PATCH 2/3] ci: format cspell config file --- build/cSpell.json | 322 +++++++++++++++++++++++----------------------- 1 file changed, 161 insertions(+), 161 deletions(-) diff --git a/build/cSpell.json b/build/cSpell.json index e5bb9e3430b1..1e16143cef0c 100644 --- a/build/cSpell.json +++ b/build/cSpell.json @@ -1,163 +1,163 @@ { - "version": "0.2", - "language": "en", - "words": [ - "Avalonia", - "binlog", - "Blazor", - "blockquotes", - "Bootstrapper", - "brotli", - "browsersync", - "bytecode", - "Callout", - "chatops", - "codebases", - "Codespace", - "Codespaces", - "Contoso", - "Cupertino", - "customizability", - "databinding", - "datacontext", - "datagrid", - "devs", - "Dismissable", - "Docfx", - "ellipsize", - "Expando", - "Framebuffer", - "Geolocation", - "globbing", - "Gyrometer", - "Hanja", - "hectopascals", - "Inlines", - "laggy", - "layouter", - "layouting", - "Listview", - "LLRM", - "mergeable", - "MSAL", - "msbuild", - "MVVM", - "NETSDK", - "netstandard", - "oidc", - "Omnisharp", - "overscroll", - "Packt", - "parameterless", - "pickable", - "Pluralsight", - "POSIX", - "reentrantly", - "roadmap", - "sandboxed", - "Segoe", - "Silverlight", - "Skia", - "skiasharp", - "Storyboarded", - "struct", - "Syncfusion", - "templatable", - "templating", - "timespan", - "Tizen", - "TLDR", - "toolkits", - "triaging", - "UI's", - "unmanaged", - "Uno's", - "unoplatform", - "UWP's", - "VSIX", - "walkthrough", - "WEBASSEMBLY" - ], - "ignoreWords": [ - "ADAL", - "Authenticode", - "automagically", - "Divio's", - "emcc", - "emscripten", - "Flatpickr", - "Giesel", - "GPIO", - "hdpi", - "Headered", - "Hoefling", - "HRESULT", - "IDBFS", - "Infragistics", - "jonathanpeppers's", - "Krueger", - "libgtk", - "Liu's", - "Matteo", - "McCaffrey", - "mdpi", - "Mergify", - "netstd", - "nventive", - "slnf", - "Stetho", - "Talkin", - "UADO", - "Udemy", - "UNOB", - "winui", - ], - "patterns": [ - { - "name": "Markdown links", - "pattern": "\\((.*)\\)", - "description": "" - }, - { - "name": "Markdown code blocks", - "pattern": "/^(\\s*`{3,}).*[\\s\\S]*?^\\1/gmx", - "description": "Taken from the cSpell example at https://cspell.org/configuration/patterns/#verbose-regular-expressions" - }, - { - "name": "Inline code blocks", - "pattern": "\\`([^\\`\\r\\n]+?)\\`", - "description": "https://stackoverflow.com/questions/41274241/how-to-capture-inline-markdown-code-but-not-a-markdown-code-fence-with-regex" - }, - { - "name": "Link contents", - "pattern": "\\", - "description": "" - }, - { - "name": "Snippet references", - "pattern": "-- snippet:(.*)", - "description": "" - }, - { - "name": "Snippet references 2", - "pattern": "\\<\\[sample:(.*)", - "description": "another kind of snippet reference" - }, - { - "name": "Multi-line code blocks", - "pattern": "/^\\s*```[\\s\\S]*?^\\s*```/gm" - } - ], - "ignoreRegExpList": [ - "Markdown links", - "Markdown code blocks", - "Inline code blocks", - "Link contents", - "Snippet references", - "Snippet references 2", - "Multi-line code blocks" - ], - "ignorePaths": [ - "../doc/index.md" - ] + "version": "0.2", + "language": "en", + "words": [ + "Avalonia", + "binlog", + "Blazor", + "blockquotes", + "Bootstrapper", + "brotli", + "browsersync", + "bytecode", + "Callout", + "chatops", + "codebases", + "Codespace", + "Codespaces", + "Contoso", + "Cupertino", + "customizability", + "databinding", + "datacontext", + "datagrid", + "devs", + "Dismissable", + "Docfx", + "ellipsize", + "Expando", + "Framebuffer", + "Geolocation", + "globbing", + "Gyrometer", + "Hanja", + "hectopascals", + "Inlines", + "laggy", + "layouter", + "layouting", + "Listview", + "LLRM", + "mergeable", + "MSAL", + "msbuild", + "MVVM", + "NETSDK", + "netstandard", + "oidc", + "Omnisharp", + "overscroll", + "Packt", + "parameterless", + "pickable", + "Pluralsight", + "POSIX", + "reentrantly", + "roadmap", + "sandboxed", + "Segoe", + "Silverlight", + "Skia", + "skiasharp", + "Storyboarded", + "struct", + "Syncfusion", + "templatable", + "templating", + "timespan", + "Tizen", + "TLDR", + "toolkits", + "triaging", + "UI's", + "unmanaged", + "Uno's", + "unoplatform", + "UWP's", + "VSIX", + "walkthrough", + "WEBASSEMBLY" + ], + "ignoreWords": [ + "ADAL", + "Authenticode", + "automagically", + "Divio's", + "emcc", + "emscripten", + "Flatpickr", + "Giesel", + "GPIO", + "hdpi", + "Headered", + "Hoefling", + "HRESULT", + "IDBFS", + "Infragistics", + "jonathanpeppers's", + "Krueger", + "libgtk", + "Liu's", + "Matteo", + "McCaffrey", + "mdpi", + "Mergify", + "netstd", + "nventive", + "slnf", + "Stetho", + "Talkin", + "UADO", + "Udemy", + "UNOB", + "winui", + ], + "patterns": [ + { + "name": "Markdown links", + "pattern": "\\((.*)\\)", + "description": "" + }, + { + "name": "Markdown code blocks", + "pattern": "/^(\\s*`{3,}).*[\\s\\S]*?^\\1/gmx", + "description": "Taken from the cSpell example at https://cspell.org/configuration/patterns/#verbose-regular-expressions" + }, + { + "name": "Inline code blocks", + "pattern": "\\`([^\\`\\r\\n]+?)\\`", + "description": "https://stackoverflow.com/questions/41274241/how-to-capture-inline-markdown-code-but-not-a-markdown-code-fence-with-regex" + }, + { + "name": "Link contents", + "pattern": "\\", + "description": "" + }, + { + "name": "Snippet references", + "pattern": "-- snippet:(.*)", + "description": "" + }, + { + "name": "Snippet references 2", + "pattern": "\\<\\[sample:(.*)", + "description": "another kind of snippet reference" + }, + { + "name": "Multi-line code blocks", + "pattern": "/^\\s*```[\\s\\S]*?^\\s*```/gm" + } + ], + "ignoreRegExpList": [ + "Markdown links", + "Markdown code blocks", + "Inline code blocks", + "Link contents", + "Snippet references", + "Snippet references 2", + "Multi-line code blocks" + ], + "ignorePaths": [ + "../doc/index.md" + ] } From 5d5d054df9eab0cf6f81b298946ab3a1c60b5456 Mon Sep 17 00:00:00 2001 From: Jerome Laban Date: Thu, 20 Oct 2022 13:44:01 -0400 Subject: [PATCH 3/3] ci: Fix transient js cleanup file --- .../Uno.UI.Wasm.Tests.csproj | 15 ++++++++++--- src/Uno.UI/Uno.UI.Wasm.csproj | 22 +++++++++---------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/Uno.UI.Wasm.Tests/Uno.UI.Wasm.Tests.csproj b/src/Uno.UI.Wasm.Tests/Uno.UI.Wasm.Tests.csproj index fbb1bdd0b78e..f4b48a671188 100644 --- a/src/Uno.UI.Wasm.Tests/Uno.UI.Wasm.Tests.csproj +++ b/src/Uno.UI.Wasm.Tests/Uno.UI.Wasm.Tests.csproj @@ -64,24 +64,33 @@ - $(TypeScriptConfigFileAdditionalFlags) --outFile $(IntermediateOutputPath)/javascript/UnitTests.js + $(TypeScriptConfigFileAdditionalFlags) --outFile $(OutputPath)/javascript/UnitTests.js <_UnoTSDefinitions Include="..\Uno.UI\bin\Uno.UI.Wasm\$(Configuration)\$(TargetFramework)\*.d.ts" /> - + - <_generatedTSFiles Include="$(IntermediateOutputPath)/javascript/*.js" /> + <_generatedTSFiles Include="$(OutputPath)/javascript/*.js" /> + + + + + + + + <_UnoEmbeddedResourcesInjectionAfterTargets Include="CompileTypeScriptWithTSConfig" /> diff --git a/src/Uno.UI/Uno.UI.Wasm.csproj b/src/Uno.UI/Uno.UI.Wasm.csproj index b9e59c4ce81b..3d8e08089051 100644 --- a/src/Uno.UI/Uno.UI.Wasm.csproj +++ b/src/Uno.UI/Uno.UI.Wasm.csproj @@ -120,37 +120,35 @@ - $(TypeScriptConfigFileAdditionalFlags) --outFile $(IntermediateOutputPath)/javascript/Uno.UI.js + $(TypeScriptConfigFileAdditionalFlags) --outFile $(OutputPath)/javascript/Uno.UI.js - + - <_unoUIDTsFilePath>$(IntermediateOutputPath)/javascript/Uno.UI.d.ts + <_unoUIDTsFilePath>$(OutputPath)/javascript/Uno.UI.d.ts - <_generatedJSFiles Include="$(IntermediateOutputPath)/javascript/*.js" /> + <_generatedJSFiles Include="$(OutputPath)/javascript/*.js" /> - - <_UnoEmbeddedResourcesInjectionAfterTargets Include="CompileTypeScriptWithTSConfig" />