Files
HawkeyeVision/VisionBuilder.UI.Blazor/Components/PreviewWindow.razor.cs
EugeneTes 34b74ecdcd path fix
2026-03-23 10:30:30 +01:00

99 lines
2.5 KiB
C#

using System.ComponentModel;
using Microsoft.AspNetCore.Components;
using OpenCvSharp;
using VisionBuilder.UI.Blazor.Helpers;
using VisionBuilder.UI.Common.ViewModel;
namespace VisionBuilder.UI.Blazor.Components;
public partial class PreviewWindow : ComponentBase, IDisposable
{
[Parameter] public PreviewVM? ViewModel { get; set; }
private string _dataUri = string.Empty;
private bool _isError;
private DateTime _lastRenderTime = DateTime.MinValue;
private Timer? _pendingTimer;
private PreviewVM? _subscribedVm;
private bool _disposed;
protected override void OnParametersSet()
{
if (_subscribedVm != ViewModel)
{
Unsubscribe();
Subscribe();
}
}
private void Subscribe()
{
_subscribedVm = ViewModel;
if (ViewModel != null)
ViewModel.PropertyChanged += OnPropertyChanged;
}
private void Unsubscribe()
{
if (_subscribedVm != null)
_subscribedVm.PropertyChanged -= OnPropertyChanged;
_subscribedVm = null;
}
private async void OnPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != nameof(PreviewVM.ImagePreview) && e.PropertyName != nameof(PreviewVM.IsError))
return;
var now = DateTime.UtcNow;
var elapsed = (now - _lastRenderTime).TotalMilliseconds;
if (elapsed < 100)
{
// Schedule a render for when the throttle window expires,
// so we always show the latest frame.
_pendingTimer?.Dispose();
_pendingTimer = new Timer(_ => RenderLatest(), null,
(int)(100 - elapsed) + 1, Timeout.Infinite);
return;
}
await RenderCurrentFrame();
}
private async void RenderLatest()
{
_pendingTimer?.Dispose();
_pendingTimer = null;
await RenderCurrentFrame();
}
private async Task RenderCurrentFrame()
{
if (_disposed) return;
_lastRenderTime = DateTime.UtcNow;
var mat = ViewModel?.ImagePreview;
var isError = ViewModel?.IsError ?? false;
string dataUri = string.Empty;
if (mat != null && !mat.Empty())
{
dataUri = mat.ToBase64DataUri();
}
_dataUri = dataUri;
_isError = isError;
await InvokeAsync(StateHasChanged);
}
public void Dispose()
{
_disposed = true;
_pendingTimer?.Dispose();
Unsubscribe();
}
}