From 4ef318973f9220a35d4d25ffa7bfa3aad030907f Mon Sep 17 00:00:00 2001 From: Loretta Date: Tue, 9 Dec 2025 11:27:21 +0100 Subject: [PATCH] Add grid sync state tracking and robust login redirection Introduce IsSyncing and OnSyncingStateChanged to IMgGridBase and MgGridBase for real-time sync state tracking and event notification. Update FruitBankToolbarTemplate to enable/disable the reload button based on grid sync and reload state, subscribing to sync events and cleaning up on disposal. Implement IAsyncDisposable in MgGridBase to prevent memory leaks. Update login navigation to use forceLoad for reliability. These changes improve UI responsiveness and resource management. --- .../Toolbars/FruitBankToolbarTemplate.razor | 79 +++++++++++++------ .../Layout/MainLayout.razor.cs | 16 +++- FruitBankHybrid.Shared/Pages/Home.razor.cs | 13 ++- 3 files changed, 82 insertions(+), 26 deletions(-) diff --git a/FruitBankHybrid.Shared/Components/Toolbars/FruitBankToolbarTemplate.razor b/FruitBankHybrid.Shared/Components/Toolbars/FruitBankToolbarTemplate.razor index 9f9ab8c..13c0672 100644 --- a/FruitBankHybrid.Shared/Components/Toolbars/FruitBankToolbarTemplate.razor +++ b/FruitBankHybrid.Shared/Components/Toolbars/FruitBankToolbarTemplate.razor @@ -1,4 +1,5 @@ -@using AyCode.Core.Loggers; +@using AyCode.Blazor.Components.Components.Grids +@using AyCode.Core.Loggers; @using AyCode.Core.Extensions @using AyCode.Core.Helpers @using AyCode.Utils.Extensions @@ -10,6 +11,8 @@ @using FruitBankHybrid.Shared.Services.Loggers; @using FruitBankHybrid.Shared.Services.SignalRs +@implements IDisposable + @inject IEnumerable LogWriters @inject FruitBankSignalRClient FruitBankSignalRClient @inject LoggedInModel LoggedInModel; @@ -30,23 +33,6 @@ - @* - - *@ - - @* @if (DxToolbarItems != null) - { - foreach (var toolBarItem in DxToolbarItems) - { - @toolBarItem - } - //@DxToolbarItem - } *@ @ToolbarItemsExtended @@ -60,20 +46,67 @@ public ToolbarBase Toolbar { get; set; } const string ExportFileName = "ExportResult"; - public bool BtnReloadDataEnabled = true; + private bool _isReloadInProgress; + private bool _isGridSyncing; + private IMgGridBase? _mgGrid; + + /// + /// Reload button is enabled only when no sync operation is in progress + /// + public bool BtnReloadDataEnabled => !_isReloadInProgress && !_isGridSyncing; + public bool EditItemsEnabled { get; set; } = true; private LoggerClient _logger; - protected override async Task OnInitializedAsync() + protected override void OnInitialized() { _logger = new LoggerClient(LogWriters.ToArray()); } + protected override void OnParametersSet() + { + // Subscribe to grid syncing state changes if Grid implements IMgGridBase + if (Grid is IMgGridBase mgGrid && !ReferenceEquals(_mgGrid, mgGrid)) + { + // Unsubscribe from previous grid + if (_mgGrid != null) + { + _mgGrid.OnSyncingStateChanged -= OnGridSyncingStateChanged; + } + + _mgGrid = mgGrid; + _mgGrid.OnSyncingStateChanged += OnGridSyncingStateChanged; + + // Get initial syncing state + _isGridSyncing = _mgGrid.IsSyncing; + } + } + + private void OnGridSyncingStateChanged(bool isSyncing) + { + _isGridSyncing = isSyncing; + InvokeAsync(StateHasChanged); + } + + public void Dispose() + { + if (_mgGrid != null) + { + _mgGrid.OnSyncingStateChanged -= OnGridSyncingStateChanged; + } + } + async Task ReloadData_Click(ToolbarItemClickEventArgs e) { - BtnReloadDataEnabled = false; - await OnReloadDataClick.InvokeAsync(); - BtnReloadDataEnabled = true; + _isReloadInProgress = true; + try + { + await OnReloadDataClick.InvokeAsync(); + } + finally + { + _isReloadInProgress = false; + } } async Task NewItem_Click() diff --git a/FruitBankHybrid.Shared/Layout/MainLayout.razor.cs b/FruitBankHybrid.Shared/Layout/MainLayout.razor.cs index a132d20..9722b1e 100644 --- a/FruitBankHybrid.Shared/Layout/MainLayout.razor.cs +++ b/FruitBankHybrid.Shared/Layout/MainLayout.razor.cs @@ -40,15 +40,27 @@ public partial class MainLayout : LayoutComponentBase { _logger = new LoggerClient(LogWriters.ToArray()); _logger.Info("OnInitializedAsync"); - var loginUri = NavManager.ToAbsoluteUri("/Login").ToString(); + FruitBankSignalRClient.OnMessageReceived += SignalRClientOnMessageReceived; + var loginUri = NavManager.ToAbsoluteUri("/Login").ToString(); if (!LoggedInModel.IsLoggedIn && NavManager.Uri != loginUri) { - NavManager.NavigateTo("/Login"); + NavManager.NavigateTo("/Login", forceLoad: true); } } + //protected override void OnAfterRender(bool firstRender) + //{ + // if (!firstRender) return; + + // var loginUri = NavManager.ToAbsoluteUri("/Login").ToString(); + // if (!LoggedInModel.IsLoggedIn && NavManager.Uri != loginUri) + // { + // NavManager.NavigateTo("/Login", forceLoad: true); + // } + //} + private async Task SignalRClientOnMessageReceived(int messageTag, string? jsonMessage) { if (messageTag != SignalRTags.NotificationReceived || !LoggedInModel.IsLoggedIn) return; diff --git a/FruitBankHybrid.Shared/Pages/Home.razor.cs b/FruitBankHybrid.Shared/Pages/Home.razor.cs index f57ddcb..d81c4fc 100644 --- a/FruitBankHybrid.Shared/Pages/Home.razor.cs +++ b/FruitBankHybrid.Shared/Pages/Home.razor.cs @@ -13,6 +13,17 @@ public partial class Home : ComponentBase protected override void OnInitialized() { - if (!LoggedInModel.IsLoggedIn) NavManager.NavigateTo("/Login"); + if (!LoggedInModel.IsLoggedIn) + { + NavManager.NavigateTo("/Login", forceLoad: true); + } } + + //protected override void OnAfterRender(bool firstRender) + //{ + // if (firstRender && !LoggedInModel.IsLoggedIn) + // { + // NavManager.NavigateTo("/Login", forceLoad: true); + // } + //} } \ No newline at end of file