From f3b33e7e1d642b20d94cd200aa7e87337431fbd3 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Mon, 11 May 2026 12:42:38 -0400 Subject: [PATCH] fix(ui/treeview): union sessionStorage keys instead of overwriting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous fix tried to defer page-side RevealNode to the second render so TreeView's async sessionStorage load could finish first. In practice Blazor Server didn't always fire a second OnAfterRenderAsync on the page after the deep-link load, so the reveal never ran. Real fix: change TreeView's storage-load to UNION the restored keys with whatever's already in _expandedKeys, instead of REPLACING. That way the page can call RevealNode whenever it wants and the storage restore can't clobber the reveal regardless of completion order. The page-side guard simplifies back to a one-shot reveal on first render. Semantic note: if a deep-link reveal expands an ancestor that the user had previously collapsed, the deep link wins. Intentional — the URL expresses the navigation intent. --- .../Components/Pages/Design/Templates.razor | 4 +--- src/ScadaLink.CentralUI/Components/Shared/TreeView.razor | 5 ++++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/ScadaLink.CentralUI/Components/Pages/Design/Templates.razor b/src/ScadaLink.CentralUI/Components/Pages/Design/Templates.razor index a969103..b02bc59 100644 --- a/src/ScadaLink.CentralUI/Components/Pages/Design/Templates.razor +++ b/src/ScadaLink.CentralUI/Components/Pages/Design/Templates.razor @@ -181,9 +181,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) { - // Wait until second render so TreeView has finished restoring its sessionStorage - // expansion state; otherwise that restore races with RevealNode and overwrites it. - if (!_revealApplied && !firstRender && TemplateIdParam > 0 && _tree != null) + if (!_revealApplied && TemplateIdParam > 0 && _tree != null) { _revealApplied = true; await _tree.RevealNode($"t:{TemplateIdParam}", select: true); diff --git a/src/ScadaLink.CentralUI/Components/Shared/TreeView.razor b/src/ScadaLink.CentralUI/Components/Shared/TreeView.razor index 2f8d85a..67c1121 100644 --- a/src/ScadaLink.CentralUI/Components/Shared/TreeView.razor +++ b/src/ScadaLink.CentralUI/Components/Shared/TreeView.razor @@ -127,7 +127,10 @@ else var keys = System.Text.Json.JsonSerializer.Deserialize>(json); if (keys != null) { - _expandedKeys = new HashSet(keys); + // Union (don't replace): callers may have invoked RevealNode before + // this async storage load completed. Preserving those reveal-added + // keys ensures deep-link reveal isn't clobbered by the restore. + foreach (var k in keys) _expandedKeys.Add(k); _initialExpansionApplied = true; } }