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.
This commit is contained in:
parent
06f397e285
commit
920bc299aa
|
|
@ -15,10 +15,18 @@ namespace AyCode.Blazor.Components.Components.Grids;
|
|||
|
||||
public interface IMgGridBase : IGrid
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether any synchronization operation is in progress
|
||||
/// </summary>
|
||||
bool IsSyncing { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when synchronization state changes (true = syncing started, false = syncing ended)
|
||||
/// </summary>
|
||||
event Action<bool>? OnSyncingStateChanged;
|
||||
}
|
||||
|
||||
public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClient> : DxGrid, IMgGridBase
|
||||
public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClient> : DxGrid, IMgGridBase, IAsyncDisposable
|
||||
where TSignalRDataSource : AcSignalRDataSource<TDataItem, TId, AcObservableCollection<TDataItem>>
|
||||
where TDataItem : class, IId<TId>
|
||||
where TId : struct
|
||||
|
|
@ -29,11 +37,18 @@ public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClie
|
|||
|
||||
protected bool IsFirstInitializeParameters;
|
||||
protected bool IsFirstInitializeParameterCore;
|
||||
private bool _isDisposed;
|
||||
|
||||
private TSignalRDataSource? _dataSource = null!;
|
||||
private AcObservableCollection<TDataItem>? _dataSourceParam = [];
|
||||
private string _gridLogName;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsSyncing => _dataSource?.IsSyncing ?? false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public event Action<bool>? OnSyncingStateChanged;
|
||||
|
||||
public MgGridBase() : base()
|
||||
{
|
||||
}
|
||||
|
|
@ -133,6 +148,7 @@ public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClie
|
|||
|
||||
public void SetGridData(object? data)
|
||||
{
|
||||
if (_isDisposed) return;
|
||||
if (ReferenceEquals(Data, data)) return;
|
||||
|
||||
BeginUpdate();
|
||||
|
|
@ -161,12 +177,25 @@ public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClie
|
|||
|
||||
_dataSource.OnDataSourceLoaded += OnDataSourceLoaded;
|
||||
_dataSource.OnDataSourceItemChanged += OnDataSourceItemChanged;
|
||||
_dataSource.OnSyncingStateChanged += OnDataSourceSyncingStateChanged;
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
private void OnDataSourceSyncingStateChanged(bool isSyncing)
|
||||
{
|
||||
if (_isDisposed) return;
|
||||
|
||||
// Forward the event to external subscribers
|
||||
OnSyncingStateChanged?.Invoke(isSyncing);
|
||||
|
||||
// Trigger UI update
|
||||
InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private async Task OnDataSourceItemChanged(ItemChangedEventArgs<TDataItem> args)
|
||||
{
|
||||
if (_isDisposed) return;
|
||||
if (args.TrackingState is TrackingState.GetAll or TrackingState.None) return;
|
||||
|
||||
Logger.Debug($"{_gridLogName} OnDataSourceItemChanged; trackingState: {args.TrackingState}");
|
||||
|
|
@ -174,7 +203,7 @@ public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClie
|
|||
var changedEventArgs = new GridDataItemChangedEventArgs<TDataItem>(this, args.Item, args.TrackingState);
|
||||
await OnGridItemChanged.InvokeAsync(changedEventArgs);
|
||||
|
||||
if (!changedEventArgs.CancelStateChangeInvoke)
|
||||
if (!changedEventArgs.CancelStateChangeInvoke && !_isDisposed)
|
||||
{
|
||||
//BeginUpdate();
|
||||
await InvokeAsync(StateHasChanged); //TODO: bezárja a DetailRow-t! pl: az email-nél IsReaded=true update... - J.
|
||||
|
|
@ -184,6 +213,8 @@ public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClie
|
|||
|
||||
private async Task OnDataSourceLoaded()
|
||||
{
|
||||
if (_isDisposed) return;
|
||||
|
||||
Logger.Debug($"{_gridLogName} OnDataSourceLoaded; Count: {_dataSource?.Count}");
|
||||
|
||||
//if(_dataSourceParam.GetType() == typeof()AcObservableCollection<TDataItem>)
|
||||
|
|
@ -192,8 +223,11 @@ public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClie
|
|||
//else Reload();
|
||||
|
||||
//_dataSource.LoadItem(_dataSource.First().Id).Forget();
|
||||
await OnDataSourceChanged.InvokeAsync(_dataSource);
|
||||
await InvokeAsync(StateHasChanged);
|
||||
if (!_isDisposed)
|
||||
{
|
||||
await OnDataSourceChanged.InvokeAsync(_dataSource);
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
|
|
@ -482,6 +516,30 @@ public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClie
|
|||
{
|
||||
return _dataSource.LoadDataSourceAsync(false);
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (_isDisposed) return;
|
||||
_isDisposed = true;
|
||||
|
||||
// Unsubscribe from events to prevent callbacks to disposed component
|
||||
if (_dataSource != null)
|
||||
{
|
||||
_dataSource.OnDataSourceLoaded -= OnDataSourceLoaded;
|
||||
_dataSource.OnDataSourceItemChanged -= OnDataSourceItemChanged;
|
||||
_dataSource.OnSyncingStateChanged -= OnDataSourceSyncingStateChanged;
|
||||
}
|
||||
|
||||
CustomizeElement -= OnCustomizeElement;
|
||||
|
||||
// Dispose base if it implements IAsyncDisposable
|
||||
if (this is IAsyncDisposable asyncDisposable && asyncDisposable != this)
|
||||
{
|
||||
await asyncDisposable.DisposeAsync();
|
||||
}
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
public class GridDataItemChangingEventArgs<TDataItem> : GridDataItemChangedEventArgs<TDataItem> where TDataItem : class
|
||||
|
|
|
|||
Loading…
Reference in New Issue