diff --git a/Ticky.Web/Components/Pages/BoardView.razor b/Ticky.Web/Components/Pages/BoardView.razor index 6f1b216..1b2724d 100644 --- a/Ticky.Web/Components/Pages/BoardView.razor +++ b/Ticky.Web/Components/Pages/BoardView.razor @@ -8,6 +8,7 @@ @inject ILogger _logger @inject IHttpContextAccessor _httpContextAccessor @inherits NotifiableBase +@implements IAsyncDisposable @if (_board is not null) { @@ -208,6 +209,7 @@ private HubConnection? _hubConnection; private HashSet _expandedSections = new(); + private bool _isDisposed; protected override void OnParametersSet() { @@ -266,6 +268,10 @@ var boardPreferences = await _protectedLocalStorage.GetAsync(Constants.StorageKeys.BoardPreferences); _preferences = (boardPreferences.Success ? boardPreferences.Value : new()) ?? new(); } + catch (JSDisconnectedException) + { + _preferences = new(); + } catch (CryptographicException) { _preferences = new(); @@ -276,6 +282,10 @@ var filterPreferences = await _protectedLocalStorage.GetAsync(FILTERS_SCOPED_KEY); _filterModel = (filterPreferences.Success ? filterPreferences.Value : new()) ?? new(); } + catch (JSDisconnectedException) + { + _filterModel = new(); + } catch(CryptographicException) { _filterModel = new(); @@ -328,6 +338,9 @@ await _hubConnection.SendAsync(nameof(UpdateHub.SubscribeBoard), Id); } catch(Exception ex) { + if (_isDisposed) + return; + _logger.LogError(ex, "Failed to start hub connection or subscribe to board {BoardId}", Id); MainLayout.RunNotification(new("Real-time updates unavailable. Please refresh the page.", NotificationType.Fail)); } @@ -341,6 +354,9 @@ { await _protectedLocalStorage.SetAsync(Constants.StorageKeys.BoardPreferences, _preferences); } + catch (JSDisconnectedException) + { + } catch (Exception ex) { _logger.LogError(ex, "Failed to save board preferences."); @@ -492,11 +508,17 @@ await LoadCardsAsync(); + if (_isDisposed) + return; + await InvokeAsync(StateHasChanged); } private async Task LoadCardsAsync() { + if (_isDisposed) + return; + ArgumentNullException.ThrowIfNull(_board); using var db = _dbContextFactory.CreateDbContext(); @@ -534,18 +556,41 @@ _cards = await queryableCards.ToListAsync(); + if (_isDisposed) + return; + await InvokeAsync(StateHasChanged); try { await _protectedLocalStorage.SetAsync(FILTERS_SCOPED_KEY, _filterModel); } + catch (JSDisconnectedException) + { + } catch (Exception ex) { _logger.LogError(ex, "Failed to save filter preferences."); } } + public async ValueTask DisposeAsync() + { + _isDisposed = true; + + if (_hubConnection is null) + return; + + try + { + await _hubConnection.DisposeAsync(); + } + catch (Exception ex) + { + _logger.LogDebug(ex, "Failed to dispose board hub connection."); + } + } + private bool IsAdmin() { if(_board is null) @@ -590,4 +635,3 @@ private bool IsExpanded(string id) => _expandedSections.Contains(id); } -