Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions src/MandoCode.Desktop/Controls/ChatTabView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,10 @@ private enum SuggestMode { None, Command, File }
public bool IsApprovalOpen => ApprovalOverlay.Visibility == Visibility.Visible
|| PlanApprovalBar.Visibility == Visibility.Visible;

/// <summary>The pending approval's headline — MainWindow shows it in the cross-tab toast.</summary>
public string ApprovalHeadline => PlanApprovalBar.Visibility == Visibility.Visible
? PlanApprovalTitle.Text : ApprovalTitle.Text;
/// <summary>The pending approval's toast summary — what's waiting (e.g. "Wants to edit
/// Program.cs"), set when the approval is shown. MainWindow shows it in the cross-tab toast.</summary>
public string ApprovalHeadline => _approvalSummary;
private string _approvalSummary = "";

/// <summary>Set by MainWindow when this tab is selected. Only a background tab badges.</summary>
public bool IsSelected { get; set; }
Expand Down Expand Up @@ -878,6 +879,10 @@ public Task<string> ShowApprovalAsync(ApprovalRequest request, CancellationToken

OnUi(() =>
{
// What the cross-tab toast will say — a specific "what's waiting" line, not the modal's
// question. Set for both the bottom-bar and modal paths.
_approvalSummary = string.IsNullOrEmpty(request.ToastSummary) ? request.Title : request.ToastSummary;

// Plan approvals render as a non-covering bottom bar so the plan card stays readable.
if (request.BottomBar)
{
Expand Down
5 changes: 4 additions & 1 deletion src/MandoCode.Desktop/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,10 @@
<!-- ======= Approval toast — top-right, shown only when an approval arrives in an agent
you're not looking at. Click = select that agent and review; X = dismiss (the tab's
gold badge stays as the passive reminder). ======= -->
<Border x:Name="ApprovalToast" Grid.ColumnSpan="2" Visibility="Collapsed"
<!-- Span ALL three columns (rail + snapshots + content) so it anchors to the window's true
top-right. Spanning only 0-1 pinned it to the collapsible Snapshots column, so it was
clipped to the rail unless that panel happened to be open. -->
<Border x:Name="ApprovalToast" Grid.Column="0" Grid.ColumnSpan="3" Visibility="Collapsed"
HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,52,20,0"
MaxWidth="380" Padding="14,12"
Background="{StaticResource MandoPanelBrush}"
Expand Down
10 changes: 9 additions & 1 deletion src/MandoCode.Desktop/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,9 @@ private void SwitchPage(string page)
? Visibility.Visible : Visibility.Collapsed;

RefreshNavIcons();
// Re-evaluate the approval toast for the new page — leaving the chat can newly "hide" the
// selected agent's approval, which should now raise the toast (and returning clears it).
RefreshTabStrip();

switch (page)
{
Expand Down Expand Up @@ -680,7 +683,12 @@ private void RefreshTabStrip()
tab.View.IsSelected = isSelected;
var badged = tab.View.IsApprovalOpen && !isSelected;
tab.Badge.Visibility = badged ? Visibility.Visible : Visibility.Collapsed;
if (badged) pending ??= tab;

// Toast for any approval you can't currently see: a background tab, OR the selected tab
// while you're away on Settings/MCP/Appearance (its chat — and the approval — is
// collapsed there, so without this you'd get no notice at all).
if (tab.View.IsApprovalOpen && (!isSelected || _currentPage != "chat"))
pending ??= tab;
}

// With several agents running, "an approval is waiting" is useless without saying where,
Expand Down
5 changes: 5 additions & 0 deletions src/MandoCode.Desktop/Services/ApprovalModels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ public sealed class ApprovalRequest
/// <summary>Render as a non-covering bottom bar rather than the centered modal. Used for plan
/// approval so the plan card stays readable in the transcript while the user decides.</summary>
public bool BottomBar { get; init; }

/// <summary>Short, specific line for the cross-agent "Approval required" toast — describes WHAT
/// is waiting (e.g. "Wants to edit Program.cs"), not the modal's question. Falls back to
/// <see cref="Title"/> when unset.</summary>
public string? ToastSummary { get; init; }
}

/// <summary>
Expand Down
6 changes: 6 additions & 0 deletions src/MandoCode.Desktop/Services/WinUiApprovalService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ public async Task<DiffApprovalResult> HandleWriteApprovalAsync(string relativePa
Subtitle = relativePath,
DiffLines = displayLines,
DiffSummary = summary,
ToastSummary = isNewFile ? $"Wants to create {fileName}" : $"Wants to edit {fileName}",
Options = options
};

Expand Down Expand Up @@ -176,6 +177,7 @@ public async Task<DiffApprovalResult> HandleCommandApprovalAsync(string command)
{
Title = "Run this command?",
CommandText = command,
ToastSummary = $"Wants to run: {(command.Length > 48 ? command[..48] + "…" : command)}",
Options = options
};

Expand Down Expand Up @@ -276,6 +278,9 @@ public async Task<DiffApprovalResult> HandleDeleteApprovalAsync(string relativeP
Subtitle = relativePath,
Detail = warning,
DiffLines = displayLines,
ToastSummary = isFolder
? $"Wants to delete folder {Path.GetFileName(relativePath)}/"
: $"Wants to delete {Path.GetFileName(relativePath)}",
Options = options
};

Expand Down Expand Up @@ -345,6 +350,7 @@ public async Task<DiffApprovalResult> HandleMcpApprovalAsync(string serverName,
{
Title = $"Allow MCP tool \"{toolName}\" from \"{serverName}\"?",
Detail = description,
ToastSummary = $"Wants to run tool \"{toolName}\"",
Options = options
};

Expand Down
1 change: 1 addition & 0 deletions src/MandoCode.Desktop/ViewModels/ChatController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,7 @@ private async Task<string> HandleProposedPlanAsync(TaskPlan plan, CancellationTo
Title = "The assistant proposes this plan. What would you like to do?",
// Bottom bar, not the centered modal — the plan card above stays readable.
BottomBar = true,
ToastSummary = "Wants to run a proposed plan",
Options = new[]
{
new ApprovalOption(ExecutePlanLabel, ApprovalOptionKind.Proceed),
Expand Down
Loading