@page "/live" @using Marathon.UI.Pages.Shared @implements IDisposable @inject IStringLocalizer L @inject IEventBrowsingService Browsing @inject EventBrowsingState BrowsingState @inject NavigationManager Nav @inject IOptionsMonitor ScrapingMonitor @L["App.Title"] ยท @L["Nav.Live"] @code { private IReadOnlyList _availableSports = Array.Empty(); private IReadOnlyList _availableCountries = Array.Empty(); private int _refreshSeconds = 30; private IDisposable? _scrapingChange; protected override async Task OnInitializedAsync() { _refreshSeconds = Math.Max(5, ScrapingMonitor.CurrentValue.PollingIntervalSeconds); _scrapingChange = ScrapingMonitor.OnChange(opts => { _refreshSeconds = Math.Max(5, opts.PollingIntervalSeconds); InvokeAsync(StateHasChanged); }); try { _availableSports = await Browsing.ListKnownSportCodesAsync(CancellationToken.None); _availableCountries = await Browsing.ListKnownCountryCodesAsync(CancellationToken.None); } catch { // Tolerate empty data sources during early phases. } } private Task> LoadAsync(EventFilter filter, CancellationToken ct) => Browsing.ListLiveAsync(filter, ct); private void HandleFilterChanged(EventBrowsingState.PageFilter next) => BrowsingState.UpdateLive(next); private void HandleRowClicked(EventListItem row) => Nav.NavigateTo($"/events/{Uri.EscapeDataString(row.Id.Value)}"); public void Dispose() => _scrapingChange?.Dispose(); }