From 64707b1f818cea92752a95344b0159d213b7d4b3 Mon Sep 17 00:00:00 2001 From: DevMando Date: Sun, 30 Aug 2026 12:58:20 -0700 Subject: [PATCH] Keep skill and MCP toggles visually stable --- CHANGELOG.md | 4 ++++ src/MandoCode.Desktop/MainWindow.Mcp.cs | 8 +++++++- src/MandoCode.Desktop/MainWindow.Skills.cs | 12 ++++++++++-- src/MandoCode.Desktop/MainWindow.ViewModels.cs | 4 ++-- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48445ae..7a55bde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,10 @@ the engine generation, so it moves 0.14.1 → 0.15.0. Desktop against a real `@directory` request. ### Fixed +- **Skill and MCP toggles no longer redraw the entire management list.** Enabling or disabling an + item now updates that toggle in place while the app applies the change to active agents. The list + keeps its current order and scroll position; it is reconciled the next time the page is opened, + filtered, or explicitly refreshed. - **The token total now reflects what the provider actually processed.** Desktop no longer adds rough character-based estimates for reads, searches, web results, writes, or attachments on top of the provider's prompt and completion counts. File reads still show their line counts. diff --git a/src/MandoCode.Desktop/MainWindow.Mcp.cs b/src/MandoCode.Desktop/MainWindow.Mcp.cs index c3f3fe4..3cb15d0 100644 --- a/src/MandoCode.Desktop/MainWindow.Mcp.cs +++ b/src/MandoCode.Desktop/MainWindow.Mcp.cs @@ -130,7 +130,13 @@ private async void McpEnabled_Toggled(object sender, RoutedEventArgs e) McpPageStatus.Text = sw.IsOn ? $"Enabling “{row.Name}”…" : $"Disabling “{row.Name}”…"; await Task.Run(() => _controller.SaveMcpServerAsync(row.Name, row.Name, server)); - await RefreshMcpListAsync(); + + // Do not replace the grouped ItemsSource for a single toggle. Recreating the list makes + // every row animate back into place and moves this server between groups while the user is + // still looking at it. The durable config and live agent tools are already updated above; + // the current view is reconciled when the page is opened again, filtered, or refreshed. + row.Enabled = sw.IsOn; + McpPageStatus.Text = sw.IsOn ? $"Enabled “{row.Name}”." : $"Disabled “{row.Name}”."; } /// Runs a slash command through the normal pipeline (transcript echo, wizard diff --git a/src/MandoCode.Desktop/MainWindow.Skills.cs b/src/MandoCode.Desktop/MainWindow.Skills.cs index 9940c86..4e94928 100644 --- a/src/MandoCode.Desktop/MainWindow.Skills.cs +++ b/src/MandoCode.Desktop/MainWindow.Skills.cs @@ -105,7 +105,9 @@ private void ApplySkillFilter() SkillsPageStatus.Text = $"{total} skill{(total == 1 ? "" : "s")}, {enabledTotal} enabled · {_skillCoordinator.UserSkillsDirectory}"; } - /// Reload every agent's skill set + prompt, then re-render the list and report. + /// Reload every agent's skill set + prompt, then re-render the list and report. + /// Use this after a structural change such as create, edit, install, delete, or an explicit + /// refresh. A simple enable/disable change deliberately keeps the current list in place. private async Task ApplySkillChangeAsync(string status) { await _skillCoordinator.ReloadAllAsync(); @@ -138,7 +140,13 @@ private async void SkillEnabled_Toggled(object sender, RoutedEventArgs e) try { _skillCoordinator.SetEnabled(row.FolderPath, sw.IsOn); - await ApplySkillChangeAsync(sw.IsOn ? $"Enabled “{row.Name}”." : $"Disabled “{row.Name}”."); + // Keep this row exactly where the user toggled it. Reapplying the grouped ItemsSource + // would remove and recreate every row, producing a distracting slide animation and + // reordering enabled/disabled groups mid-click. The persisted state is reconciled on + // the next page open, filter change, or explicit refresh. + row.Enabled = sw.IsOn; + await _skillCoordinator.ReloadAllAsync(); + SkillsPageStatus.Text = sw.IsOn ? $"Enabled “{row.Name}”." : $"Disabled “{row.Name}”."; } catch (Exception ex) { diff --git a/src/MandoCode.Desktop/MainWindow.ViewModels.cs b/src/MandoCode.Desktop/MainWindow.ViewModels.cs index b843feb..0c1bc66 100644 --- a/src/MandoCode.Desktop/MainWindow.ViewModels.cs +++ b/src/MandoCode.Desktop/MainWindow.ViewModels.cs @@ -192,7 +192,7 @@ public sealed class McpRow public string Status { get; init; } = ""; public SolidColorBrush StatusBrush { get; init; } = new(Colors.Gray); /// Per-server on/off (the config's Disabled flag, inverted). Shared by every agent. - public bool Enabled { get; init; } + public bool Enabled { get; set; } } /// A section of the skills list (e.g. "Enabled (12)"). A List subclass so a @@ -218,7 +218,7 @@ public sealed class SkillRow public string Description { get; init; } = ""; public string Body { get; init; } = ""; public string FolderPath { get; init; } = ""; - public bool Enabled { get; init; } + public bool Enabled { get; set; } // Size of the instructions body — what gets injected into the prompt on load, so it's the cost // that spins a local model up. ~4 chars/token is the usual rough estimate.