fix(ui): gate Mission Control submit-for-review, add retry, fix event leak

Submit for Review is now disabled while a ConPTY pane is starting, has
failed to launch, or has already exited, and MissionControlViewModel
guards against a rapid double-click racing two SubmitTaskForReviewAsync
calls. A failed launch no longer permanently occupies its TaskId dedupe
slot -- a Retry button re-fetches the launch spec and restarts the pane
in place. CloseConPtySession/Dispose now also unsubscribe
SubmitForReviewRequested, matching the other pane event handlers. Also
fixes the pre-existing nullable-dereference warning in
IslandsShellViewModel.SyncInteractiveSessionChips.
This commit is contained in:
mika kuns
2026-08-06 13:42:06 +02:00
parent 0d1e3b9a6f
commit 57c61a2043
9 changed files with 299 additions and 8 deletions
@@ -302,16 +302,22 @@ public sealed partial class MissionControlViewModel : ViewModelBase, IDisposable
// Submit a task's hand-driven ConPTY work for review, then close the pane (the interactive
// session is finished). The worker commits the worktree and moves the task to WaitingForReview.
// Guarded by the pane's IsSubmitPending flag — a rapid double-click would otherwise race two
// SubmitTaskForReviewAsync calls, with the loser flashing a spurious footer error.
private async void OnPaneSubmitForReview(string taskId)
{
if (ConPtySessions.FirstOrDefault(s => s.TaskId == taskId) is not { } pane || pane.IsSubmitPending)
return;
pane.IsSubmitPending = true;
try
{
await _worker.SubmitTaskForReviewAsync(taskId);
if (ConPtySessions.FirstOrDefault(s => s.TaskId == taskId) is { } pane)
CloseConPtySession(pane);
CloseConPtySession(pane);
}
catch (Exception ex)
{
pane.IsSubmitPending = false;
ErrorReported?.Invoke(Loc.T("missionControl.submitForReviewFailed", ex.Message));
}
}
@@ -321,6 +327,7 @@ public sealed partial class MissionControlViewModel : ViewModelBase, IDisposable
if (!ConPtySessions.Contains(pane)) return;
pane.ErrorReported -= OnConPtyPaneError;
pane.CloseRequested -= CloseConPtySession;
pane.SubmitForReviewRequested -= OnPaneSubmitForReview;
ConPtySessions.Remove(pane);
pane.Dispose();
}
@@ -370,6 +377,7 @@ public sealed partial class MissionControlViewModel : ViewModelBase, IDisposable
{
c.ErrorReported -= OnConPtyPaneError;
c.CloseRequested -= CloseConPtySession;
c.SubmitForReviewRequested -= OnPaneSubmitForReview;
c.Dispose();
}
ConPtySessions.Clear();