-
Notifications
You must be signed in to change notification settings - Fork 832
Refactor in app HR handling #22009
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
base: master
Are you sure you want to change the base?
Refactor in app HR handling #22009
Conversation
|
Note: This is a draft PR as the final goal is to split the "Dev Server client" from the "Hot Reload" logic as they are no longer deeply inter-dependent. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR refactors the hot reload UI update pause/resume functionality by extracting it from the TypeMappings class into a dedicated HotReloadService class. It also simplifies visual tree enumeration from async to synchronous iteration, improving code readability and maintainability.
Key Changes:
- Introduced
HotReloadServicewith a disposableUIUpdatePauseHandlepattern for pausing/resuming UI updates - Refactored
TypeMappingsto useImmutableDictionaryfor thread-safe type mapping storage - Simplified visual tree enumeration from async
IAsyncEnumerableto synchronousIEnumerablewith directforeachloops
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| HotReloadService.cs | New dedicated service for managing hot-reload UI update pausing with disposable handle pattern |
| ElementUpdateHandlerCollection.cs | New collection class for efficiently managing and caching element update handlers |
| TypeMappings.cs | Refactored to use ImmutableDictionary and removed pause/resume logic (moved to HotReloadService) |
| ClientHotReloadProcessor.cs | Added singleton initialization and HotReloadService integration |
| ClientHotReloadProcessor.Status.cs | Made internal members accessible and added optional source parameter |
| ClientHotReloadProcessor.MetadataUpdate.cs | Major refactoring: multi-window support, synchronous tree iteration, improved error handling |
| ClientHotReloadProcessor.Common.cs | Simplified visual tree enumeration to synchronous iteration |
| RemoteControlExtensions.cs | Updated to use HotReloadService.IsUIUpdatePaused instead of TypeMappings |
| Given_TextBlock.cs | Updated test to use new PauseUIUpdates() disposable pattern |
| Given_Frame.cs | Updated tests to use new PauseUIUpdates() disposable pattern |
| BaseTestClass.cs | Removed TypeMappings.ClearMappings() and TypeMappings.Resume() calls from test initialization |
| if (windows is null or { Count: 0 }) | ||
| { | ||
| if (_log.IsEnabled(LogLevel.Error)) | ||
| var errorMsg = "Cannot update UI as no window has been found. Make sure you have enabled hot-reload (Window.UseStudio()) in app startup. See https://aka.platform.uno/hot-reloa"; |
Copilot
AI
Dec 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in URL: "hot-reloa" appears to be truncated and should be "hot-reload".
| var errorMsg = "Cannot update UI as no window has been found. Make sure you have enabled hot-reload (Window.UseStudio()) in app startup. See https://aka.platform.uno/hot-reloa"; | |
| var errorMsg = "Cannot update UI as no window has been found. Make sure you have enabled hot-reload (Window.UseStudio()) in app startup. See https://aka.platform.uno/hot-reload"; |
| UIUpdated = 200, | ||
|
|
||
| /// <summary> | ||
| /// Indicates that the UI ahs not been updated to latest changes because another process is holding the updates. |
Copilot
AI
Dec 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in documentation: "ahs" should be "has".
| /// Indicates that the UI ahs not been updated to latest changes because another process is holding the updates. | |
| /// Indicates that the UI has not been updated to latest changes because another process is holding the updates. |
|
|
||
| // Invoke initializers so default types and other resources get updated. | ||
| registerResourceDictionariesBySourceLocalMethod.Invoke(null, null); | ||
| // This is needed for the head only (causes some extra invalid registration ins the ResourceResolver, but it has no negative impact) |
Copilot
AI
Dec 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing space in comment: "Ins" should be "in". The comment says "extra invalid registration ins the ResourceResolver" but should read "extra invalid registration in the ResourceResolver".
| // This is needed for the head only (causes some extra invalid registration ins the ResourceResolver, but it has no negative impact) | |
| // This is needed for the head only (causes some extra invalid registration in the ResourceResolver, but it has no negative impact) |
| using static Uno.UI.RemoteControl.HotReload.MetadataUpdater.ElementUpdateAgent; | ||
| using Microsoft.VisualBasic; | ||
| using static Microsoft.UI.Xaml.Controls.CollectionChangedOperation; | ||
| using System.Xml.Linq; |
Copilot
AI
Dec 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing System.Xml.Linq namespace: The using statement for System.Xml.Linq at line 28 appears to be unused. If it's not needed, it should be removed for code cleanliness.
| using System.Xml.Linq; |
| #if HAS_UNO | ||
| var windows = ApplicationHelper.Windows; | ||
| #else | ||
| IReadOnlyList<Window> windows = CurrentWindow is { } cw ? [cw] : []; |
Copilot
AI
Dec 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent conditional compilation: At line 91, the #else branch references CurrentWindow which is undefined. The field was renamed to _mainWindow at line 43, but this reference wasn't updated. This will cause a compilation error on non-HAS_UNO platforms.
| IReadOnlyList<Window> windows = CurrentWindow is { } cw ? [cw] : []; | |
| IReadOnlyList<Window> windows = _mainWindow is { } cw ? [cw] : []; |
| #if __APPLE_UIKIT__ | ||
| using UIKit; | ||
| using _View = UIKit.UIView; |
Copilot
AI
Dec 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate conditional compilation directives: The #if __APPLE_UIKIT__ block for UIKit imports appears twice (lines 23-24 and lines 29-31). The second block should be removed as it's redundant.
| public void InitHotReload() | ||
| { | ||
| TypeMappings.ClearMappings(); | ||
|
|
||
| // Make sure type mappings is running | ||
| TypeMappings.Resume(); | ||
| } |
Copilot
AI
Dec 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Consider test isolation: The TypeMappings.ClearMappings() call was removed from test initialization. With the new ImmutableDictionary approach, type mappings will persist across tests, which could lead to unexpected test interactions. Consider whether this is intentional or if a cleanup mechanism is still needed for test isolation.
| internal static void Init(ClientHotReloadProcessor processor) | ||
| { | ||
| _instance = new(processor); | ||
| } |
Copilot
AI
Dec 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing documentation: The Init method is marked as internal and is a critical initialization point for the service, but it lacks XML documentation. Consider adding documentation to explain when and how this method should be called, especially given the comment at line 35 about replacing it with a module initializer.
| using Microsoft.VisualBasic; | ||
| using static Microsoft.UI.Xaml.Controls.CollectionChangedOperation; |
Copilot
AI
Dec 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary using statements: Microsoft.VisualBasic and static Microsoft.UI.Xaml.Controls.CollectionChangedOperation are imported but never used in this file. These should be removed to keep the code clean.
| using Microsoft.VisualBasic; | |
| using static Microsoft.UI.Xaml.Controls.CollectionChangedOperation; |
|
|
||
| #region Legacy temp compat members | ||
| // For now, this is initialized when the ClientHRProcessor initializes. | ||
| // But this should be replaced ny a module initializer in the main application. |
Copilot
AI
Dec 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in comment: "ny" should be "by" in the comment "But this should be replaced ny a module initializer".
| // But this should be replaced ny a module initializer in the main application. | |
| // But this should be replaced by a module initializer in the main application. |
|
🤖 Your Docs stage site is ready! Visit it here: https://unodocsprstaging.z13.web.core.windows.net/pr-22009/docs/index.html |
|
🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-22009/wasm-skia-net9/index.html |
carldebilly
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
✨ Feature
What is the current behavior? 🤔
TypeMappingsclassToArrayWhat is the new behavior? 🚀
foreachPR Checklist ✅
Screenshots Compare Test Runresults.