From 1b5827b8f460b1c53181f407659112d9dd852731 Mon Sep 17 00:00:00 2001 From: Justin Paul Date: Fri, 8 May 2026 12:32:11 -0400 Subject: [PATCH] v0.1.4: Rollback NRE fix + Gitea Actions builds (#8) * Fix Rollback NRE: capture filename before refreshing the checkpoint list The actual restore on the service was succeeding but the GUI showed "Rollback failed: Object reference not set to an instance of an object." because RefreshAsync clears the ObservableCollection, the SelectedItem binding goes null when its source item disappears, and the next line dereferenced Selected!.FileName. Cache the filename and timestamp before any await so the post-refresh status update doesn't depend on Selected still being non-null. Co-Authored-By: Claude Opus 4.7 (1M context) * v0.1.4 --------- Co-authored-by: Claude Opus 4.7 (1M context) --- Directory.Build.props | 2 +- .../ViewModels/ConfigCheckpointsViewModel.cs | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 4f3a527..78ecee5 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 0.1.3 + 0.1.4 Justin Paul Justin Paul Webhook Server diff --git a/src/WebhookServer.Gui/ViewModels/ConfigCheckpointsViewModel.cs b/src/WebhookServer.Gui/ViewModels/ConfigCheckpointsViewModel.cs index d0fa3fc..817cc68 100644 --- a/src/WebhookServer.Gui/ViewModels/ConfigCheckpointsViewModel.cs +++ b/src/WebhookServer.Gui/ViewModels/ConfigCheckpointsViewModel.cs @@ -82,8 +82,14 @@ public sealed partial class ConfigCheckpointsViewModel : ObservableObject { if (Selected is null) return; + // Capture before the refresh; the ObservableCollection.Clear() in + // RefreshAsync nulls Selected (the original instance is gone from the + // collection so the SelectedItem binding clears). + var fileName = Selected.FileName; + var savedAt = Selected.SavedAt; + var ok = MessageBox.Show( - $"Roll the configuration back to the checkpoint from {Selected.SavedAt.ToLocalTime():yyyy-MM-dd HH:mm:ss}?\n\nThe current configuration is automatically saved as a new checkpoint first, so you can roll forward again.", + $"Roll the configuration back to the checkpoint from {savedAt.ToLocalTime():yyyy-MM-dd HH:mm:ss}?\n\nThe current configuration is automatically saved as a new checkpoint first, so you can roll forward again.", "Confirm rollback", MessageBoxButton.OKCancel, MessageBoxImage.Warning); @@ -91,10 +97,10 @@ public sealed partial class ConfigCheckpointsViewModel : ObservableObject try { - await _client.RestoreBackupAsync(Selected.FileName).ConfigureAwait(false); + await _client.RestoreBackupAsync(fileName).ConfigureAwait(false); await RefreshAsync().ConfigureAwait(false); Application.Current.Dispatcher.Invoke(() => - StatusMessage = $"Rolled back to {Selected!.FileName}."); + StatusMessage = $"Rolled back to {fileName}."); } catch (Exception ex) {