fix(ui): stop app crash when approving review after Merge all

The Details island review commands (Approve/Reject/Park/Cancel) invoked the
hub without catching exceptions. After "Merge all" folds the parent out of
WaitingForReview, pressing Approve made the hub throw a HubException, which
escaped the generated AsyncRelayCommand as an unobserved async-void exception
and crashed the app. Wrap the calls in try/catch like the Tasks island does;
the TaskUpdated broadcast reconciles the UI.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-06-04 18:04:37 +02:00
parent 22a1ba7f30
commit cc7355eaa4
2 changed files with 36 additions and 5 deletions

View File

@@ -1267,7 +1267,11 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
private async System.Threading.Tasks.Task ApproveReviewAsync()
{
if (Task is null || !_worker.IsConnected) return;
await _worker.ApproveReviewAsync(Task.Id);
// The hub rejects (HubException) if the task is no longer WaitingForReview
// — e.g. after "Merge all" folded the parent. Swallow it; the TaskUpdated
// broadcast reconciles the UI. An unhandled command exception would crash.
try { await _worker.ApproveReviewAsync(Task.Id); }
catch { /* stale review action; broadcast reconciles */ }
}
[RelayCommand]
@@ -1276,7 +1280,8 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
if (Task is null || !_worker.IsConnected) return;
var feedback = ReviewFeedback;
if (string.IsNullOrWhiteSpace(feedback)) return;
await _worker.RejectReviewToQueueAsync(Task.Id, feedback);
try { await _worker.RejectReviewToQueueAsync(Task.Id, feedback); }
catch { /* stale review action; broadcast reconciles */ return; }
ReviewFeedback = "";
}
@@ -1284,14 +1289,16 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
private async System.Threading.Tasks.Task ParkReviewAsync()
{
if (Task is null || !_worker.IsConnected) return;
await _worker.RejectReviewToIdleAsync(Task.Id);
try { await _worker.RejectReviewToIdleAsync(Task.Id); }
catch { /* stale review action; broadcast reconciles */ }
}
[RelayCommand]
private async System.Threading.Tasks.Task CancelReviewAsync()
{
if (Task is null || !_worker.IsConnected) return;
await _worker.CancelReviewAsync(Task.Id);
try { await _worker.CancelReviewAsync(Task.Id); }
catch { /* stale review action; broadcast reconciles */ }
}
// ── Diff meter parser ───────────────────────────────────────────────────────