Skip to content

Commit

Permalink
feat: Controlling ui updates on hot reload resume
Browse files Browse the repository at this point in the history
  • Loading branch information
nickrandolph committed Nov 24, 2023
1 parent 6819a22 commit 159cce7
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,12 @@ private static async Task<bool> ShouldReload()
}
try
{
await TypeMappings.WaitForMappingsToResume();
return await TypeMappings.WaitForMappingsToResume();
}
finally
{
Interlocked.Exchange(ref _isReloading, 0);
}
return true;
}

internal static Window? CurrentWindow { get; set; }
Expand Down
12 changes: 11 additions & 1 deletion src/Uno.UI.RemoteControl/HotReload/WindowExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Uno.UI.RemoteControl.HotReload;
using System;
using Uno.UI.RemoteControl.HotReload;
using Windows.UI.Xaml;

namespace Uno.UI;
Expand All @@ -13,4 +14,13 @@ public static class WindowExtensions
/// </summary>
/// <param name="window">The window of the application where UI updates will be applied</param>
public static void EnableHotReload(this Window window) => ClientHotReloadProcessor.CurrentWindow = window;

/// <summary>
/// Forces the layout of the window to be update with any HotReload changes
/// that may have occurred when Hot Reload updating was paused
/// </summary>
/// <param name="window">The window of the application to be updated</param>
/// <remarks>Currently this method doesn't use the window instance. However, with the addition of multi-window
/// support it's likely that the instance will be needed to deterine the window where updates will be applied</remarks>
public static void ForceHotReloadUpdate(this Window window) => ClientHotReloadProcessor.UpdateApplication(Array.Empty<Type>());
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Uno.Extensions;
using Uno.UI.Helpers;
using Uno.UI;
using Uno.UI.RuntimeTests.Tests.HotReload.Frame.HRApp.Tests;
using Uno.UI.RuntimeTests.Tests.HotReload.Frame.Pages;

Expand Down Expand Up @@ -120,6 +121,62 @@ await HotReloadHelper.UpdateServerFileAndRevert<HR_Frame_Pages_Page1>(
}


/// <summary>
/// Checks that a simple change to a XAML element (change Text on TextBlock) will not be applied to
/// the currently visible page when HR is paused and that the change will be applied once HR is resumed
/// Open Page1
/// Pause HR
/// Change Page1 (no changes to Page1 UI)
/// Resume HR (changes applied to Page1 UI)
/// </summary>
[TestMethod]
public async Task Check_Can_Change_Page1_Pause_NoUIUpdate_HR()
{
var ct = new CancellationTokenSource(TimeSpan.FromSeconds(10)).Token;

var frame = new Windows.UI.Xaml.Controls.Frame();
UnitTestsUIContentHelper.Content = frame;

frame.Navigate(typeof(HR_Frame_Pages_Page1));

// Check the initial text of the TextBlock
await frame.ValidateTextOnChildTextBlock(FirstPageTextBlockOriginalText);

// Pause HR
TypeMappings.Pause();
try
{

// Check the text of the TextBlock is the same even after a HR change (since HR is paused)
await HotReloadHelper.UpdateServerFileAndRevert<HR_Frame_Pages_Page1>(
FirstPageTextBlockOriginalText,
FirstPageTextBlockChangedText,
async () =>
{
await frame.ValidateTextOnChildTextBlock(FirstPageTextBlockOriginalText);
},
ct);
}
finally
{
// Resume HR
TypeMappings.Resume(false);
}

// Although HR has been un-paused (resumed) the UI should not have updated at this point
// due to false parameter passed to Resume method
await frame.ValidateTextOnChildTextBlock(FirstPageTextBlockOriginalText);

// Force a refresh
Window.Current.ForceHotReloadUpdate();

await TestingUpdateHandler.WaitForVisualTreeUpdate().WaitAsync(ct);

// Check that the text has been updated
await frame.ValidateTextOnChildTextBlock(FirstPageTextBlockOriginalText);
}


/// <summary>
/// Checks that a simple xaml change to the current page will be retained when
/// navigating forward to a new page and then going back to the original page
Expand Down
12 changes: 7 additions & 5 deletions src/Uno.UI/Helpers/TypeMappings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,10 @@ internal static void ClearMappings()
/// </summary>
/// <returns>A task that will complete when type mapping collection
/// has resumed. Returns a completed task if type mapping collection
/// is currently active</returns>
public static Task WaitForMappingsToResume()
=> _mappingsPaused is not null ? _mappingsPaused.Task : Task.CompletedTask;
/// is currently active
/// The value (bool) returned from the task indicates whether the layout should be updated</returns>
public static Task<bool> WaitForMappingsToResume()
=> _mappingsPaused is not null ? _mappingsPaused.Task : Task.FromResult(true);

/// <summary>
/// Pause the collection of type mappings.
Expand All @@ -139,15 +140,16 @@ public static void Pause()
/// was paused, those new mappings will be applied before
/// the WaitForMappingsToResume task completes
/// </summary>
public static void Resume()
/// <param name="updateLayout">Indicates whether the layout should be updated after resuming updates</param>
public static void Resume(bool updateLayout = true)
{
var completion = _mappingsPaused;
_mappingsPaused = null;
if (completion is not null)
{
MappedTypeToOrignalTypeMapings = AllMappedTypeToOrignalTypeMapings.ToDictionary(x => x.Key, x => x.Value);
OriginalTypeToMappedType = AllOriginalTypeToMappedType.ToDictionary(x => x.Key, x => x.Value);
completion.TrySetResult(true);
completion.TrySetResult(updateLayout);
}
}
}

0 comments on commit 159cce7

Please sign in to comment.