Skip to content

Commit

Permalink
feat: Generate HotReload-friendly merged file when HR is enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
Youssef1313 committed Nov 8, 2023
1 parent d26ff55 commit 69d2d87
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

<PropertyGroup>
<Authors>unoplatform</Authors>
<LangVersion>11</LangVersion>
<PackageProjectUrl>https://github.com/unoplatform/uno.xamlmerge.task</PackageProjectUrl>
<PackageIconUrl>https://nv-assets.azurewebsites.net/logos/uno.png</PackageIconUrl>
<RepositoryUrl>https://github.com/unoplatform/uno.xamlmerge.task</RepositoryUrl>
Expand Down
74 changes: 74 additions & 0 deletions src/Uno.XamlMerge.Task/BatchMergeXaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;

namespace Uno.UI.Tasks.BatchMerge
Expand All @@ -28,6 +29,9 @@ public class BatchMergeXaml_v0 : CustomTask
[Required]
public string ProjectFullPath { get; set; }

[Required]
public bool IsHotReloadEnabled { get; set; }

[Output]
public string[] FilesWritten
=> _filesWritten.ToArray();
Expand All @@ -44,6 +48,12 @@ public override bool Execute()
var filteredPages = Pages.ToList();
filteredPages.RemoveAll(e => MergedXamlFiles.Any(m => FullPathComparer.Default.Equals(e, m)));

if (IsHotReloadEnabled)
{
GenerateForHotReload(filteredPages);
return !HasLoggedErrors;
}

if (MergedXamlFiles.Length > 1)
{
foreach (var mergedXamlFile in MergedXamlFiles)
Expand All @@ -69,6 +79,70 @@ public override bool Execute()
return !HasLoggedErrors;
}

private string GenerateMergedDictionariesForHotReload(IEnumerable<ITaskItem> filteredPages)
{
var projectBasePath = Path.GetDirectoryName(Path.GetFullPath(ProjectFullPath));

var builder = new StringBuilder();
builder.Append("""
<!-- Generating a resource dictionary that references existing dictionaries for HotReload support -->
<!-- Proper merging of XAML files will happen if you build in Release configuration -->
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
<ResourceDictionary.MergedDictionaries>
""");

foreach (var page in filteredPages)
{
var pagePath = Path.GetFullPath(page.ItemSpec).Replace(projectBasePath, "").TrimStart(Path.DirectorySeparatorChar);
builder.Append($"""
<ResourceDictionary Source="ms-appx:///{pagePath}" />
""");
}

builder.Append("""
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
""");

return builder.ToString();
}

/// <summary>
/// When HotReload is enabled, we want modifications to the original XAML files to be reflected.
/// This cannot be achieved when an actual merge happens.
/// So, for HotReload, we'll generate a XAML file that only references the original XAML files and not do an actual merge.
/// This way, it can work with HotReload perfectly.
/// </summary>
private void GenerateForHotReload(List<ITaskItem> filteredPages)
{
if (MergedXamlFiles.Length > 1)
{
foreach (var mergedXamlFile in MergedXamlFiles)
{
var mergeFileName = Path.GetFileName(mergedXamlFile.ItemSpec);
string fileContents = GenerateMergedDictionariesForHotReload(filteredPages.Where(p => string.Equals(p.GetMetadata("MergeFile"), mergeFileName, StringComparison.OrdinalIgnoreCase)));

Directory.CreateDirectory(Path.GetDirectoryName(mergedXamlFile.ItemSpec));
Utils.RewriteFileIfNecessary(mergedXamlFile.ItemSpec, fileContents);
}
}
else if (MergedXamlFiles.Length == 1)
{
// Single target file, without "MergeFile" attribution
var mergedXamlFile = MergedXamlFiles[0];
var mergeFileName = Path.GetFileName(mergedXamlFile.ItemSpec);
string fileContents = GenerateMergedDictionariesForHotReload(filteredPages);

Directory.CreateDirectory(Path.GetDirectoryName(mergedXamlFile.ItemSpec));
Utils.RewriteFileIfNecessary(mergedXamlFile.ItemSpec, fileContents);
}
}

private void ValidatePageMergeFileMetadata()
{
if (MergedXamlFiles.Length > 1)
Expand Down
1 change: 0 additions & 1 deletion src/Uno.XamlMerge.Task/Uno.XamlMerge.Task.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
<TargetFramework>netstandard2.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>10.0</LangVersion>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<IsTool>true</IsTool>
<AssemblyName>Uno.XamlMerge.Task.v0</AssemblyName>
Expand Down
2 changes: 2 additions & 0 deletions src/Uno.XamlMerge.Task/build/Uno.XamlMerge.Task.targets
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
DependsOnTargets="_XamlMergeFillProperties"
Condition="'$(BuildingProject)' == 'true' or '$(DesignTimeBuild)' != 'true'">

<!-- TODO: Is Configuration==Debug the right value for IsHotReloadEnabled? -->
<BatchMergeXaml_v0
ProjectFullPath="$(MSBuildProjectFullPath)"
Pages="@(XamlMergeInput)"
IsHotReloadEnabled="'$(Configuration)' == 'Debug'"
MergedXamlFiles="@(XamlMergeOutputFiles)" />
<Message Text="Merged resources XAML file was generated in $(XamlMergeOutputFile)" />

Expand Down
7 changes: 4 additions & 3 deletions src/Uno.XamlMerge.Tests/Given_BatchMergeXaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ public void When_Empty()
}

[TestMethod]
public void When_Key_TargeType_Conflict()
public void When_HR_Enabled()
{
var task = CreateMerger();
var task = CreateMerger(isHotReloadEnabled: true);

Assert.IsTrue(task.Execute());

Expand Down Expand Up @@ -324,7 +324,7 @@ private void ValidateOutput(BatchMergeXaml_v0 task, [CallerMemberName] string te
}
}

private BatchMergeXaml_v0 CreateMerger([CallerMemberName] string testName = "")
private BatchMergeXaml_v0 CreateMerger(bool isHotReloadEnabled = false, [CallerMemberName] string testName = "")
{
var basePath = GetBasePath(testName);

Expand Down Expand Up @@ -364,6 +364,7 @@ private BatchMergeXaml_v0 CreateMerger([CallerMemberName] string testName = "")
.Distinct()
.Select(f => new TaskItem(Path.Combine(basePath, "Output", f)))
.ToArray();
task.IsHotReloadEnabled = isHotReloadEnabled;
return task;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">

<x:String x:Key="Key1">Value1</x:String>
</ResourceDictionary>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">

<x:String x:Key="Key2">Value2</x:String>
</ResourceDictionary>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!-- Generating a resource dictionary that references existing dictionaries for HotReload support -->
<!-- Proper merging of XAML files will happen if you build in Release configuration -->
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ms-appx:///When_HR_Enabled\Input_Dictionary_1.xml" /> <ResourceDictionary Source="ms-appx:///When_HR_Enabled\Input_Dictionary_2.xml" /> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
1 change: 0 additions & 1 deletion src/Uno.XamlMerge.Tests/Uno.XamlMerge.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

<PropertyGroup>
<TargetFrameworks>net6.0;net461</TargetFrameworks>
<LangVersion>10</LangVersion>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
Expand Down

0 comments on commit 69d2d87

Please sign in to comment.