-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Fix duplicate dock band pins #46637
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Fix duplicate dock band pins #46637
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -499,17 +499,6 @@ public void UnpinCommand(string commandId, IServiceProvider serviceProvider) | |||||||||||||||||||||||||||||||||||||
| public void PinDockBand(string commandId, IServiceProvider serviceProvider, Dock.DockPinSide side = Dock.DockPinSide.Start, bool? showTitles = null, bool? showSubtitles = null) | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| var settingsService = serviceProvider.GetRequiredService<ISettingsService>(); | ||||||||||||||||||||||||||||||||||||||
| var settings = settingsService.Settings; | ||||||||||||||||||||||||||||||||||||||
| var dockSettings = settings.DockSettings; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Prevent duplicate pins — check all sections | ||||||||||||||||||||||||||||||||||||||
| if (dockSettings.StartBands.Any(b => b.CommandId == commandId && b.ProviderId == this.ProviderId) || | ||||||||||||||||||||||||||||||||||||||
| dockSettings.CenterBands.Any(b => b.CommandId == commandId && b.ProviderId == this.ProviderId) || | ||||||||||||||||||||||||||||||||||||||
| dockSettings.EndBands.Any(b => b.CommandId == commandId && b.ProviderId == this.ProviderId)) | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| Logger.LogDebug($"Dock band '{commandId}' from provider '{this.ProviderId}' is already pinned; skipping."); | ||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| var bandSettings = new DockBandSettings | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -523,6 +512,18 @@ public void PinDockBand(string commandId, IServiceProvider serviceProvider, Dock | |||||||||||||||||||||||||||||||||||||
| s => | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| var dockSettings = s.DockSettings; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Prevent duplicate pins — check inside the CAS lambda so | ||||||||||||||||||||||||||||||||||||||
| // the guard is re-evaluated on every retry against the | ||||||||||||||||||||||||||||||||||||||
| // latest snapshot. | ||||||||||||||||||||||||||||||||||||||
| if (dockSettings.StartBands.Any(b => b.CommandId == commandId && b.ProviderId == this.ProviderId) || | ||||||||||||||||||||||||||||||||||||||
| dockSettings.CenterBands.Any(b => b.CommandId == commandId && b.ProviderId == this.ProviderId) || | ||||||||||||||||||||||||||||||||||||||
| dockSettings.EndBands.Any(b => b.CommandId == commandId && b.ProviderId == this.ProviderId)) | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| Logger.LogDebug($"Dock band '{commandId}' from provider '{this.ProviderId}' is already pinned; skipping."); | ||||||||||||||||||||||||||||||||||||||
| return s; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| return s with | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| DockSettings = side switch | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -583,6 +584,14 @@ internal void PinDockBand(TopLevelViewModel bandVm) | |||||||||||||||||||||||||||||||||||||
| Logger.LogDebug($"CommandProviderWrapper.PinDockBand: {ProviderId} - {bandVm.Id}"); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| var bands = this.DockBandItems.ToList(); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Prevent duplicate entries in the in-memory band list | ||||||||||||||||||||||||||||||||||||||
| if (bands.Any(b => b.Id == bandVm.Id)) | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| Logger.LogDebug($"Dock band '{bandVm.Id}' already exists in DockBandItems; skipping."); | ||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
Comment on lines
586
to
+594
|
||||||||||||||||||||||||||||||||||||||
| var bands = this.DockBandItems.ToList(); | |
| // Prevent duplicate entries in the in-memory band list | |
| if (bands.Any(b => b.Id == bandVm.Id)) | |
| { | |
| Logger.LogDebug($"Dock band '{bandVm.Id}' already exists in DockBandItems; skipping."); | |
| return; | |
| } | |
| var existingBands = this.DockBandItems; | |
| // Prevent duplicate entries in the in-memory band list | |
| if (existingBands.Any(b => b.Id == bandVm.Id)) | |
| { | |
| Logger.LogDebug($"Dock band '{bandVm.Id}' already exists in DockBandItems; skipping."); | |
| return; | |
| } | |
| var bands = existingBands.ToList(); |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -85,9 +85,19 @@ private void SetupBands( | |||||||||||||||||||||||||||||||
| ObservableCollection<DockBandViewModel> target) | ||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||
| List<DockBandViewModel> newBands = new(); | ||||||||||||||||||||||||||||||||
| HashSet<string> seen = new(StringComparer.Ordinal); | ||||||||||||||||||||||||||||||||
| foreach (var band in bands) | ||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||
| var commandId = band.CommandId; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| // Skip duplicate entries that share the same provider + command id | ||||||||||||||||||||||||||||||||
| var key = $"{band.ProviderId}\0{commandId}"; | ||||||||||||||||||||||||||||||||
| if (!seen.Add(key)) | ||||||||||||||||||||||||||||||||
|
Comment on lines
+88
to
+95
|
||||||||||||||||||||||||||||||||
| HashSet<string> seen = new(StringComparer.Ordinal); | |
| foreach (var band in bands) | |
| { | |
| var commandId = band.CommandId; | |
| // Skip duplicate entries that share the same provider + command id | |
| var key = $"{band.ProviderId}\0{commandId}"; | |
| if (!seen.Add(key)) | |
| HashSet<(string ProviderId, string CommandId)> seen = new(); | |
| foreach (var band in bands) | |
| { | |
| var commandId = band.CommandId; | |
| // Skip duplicate entries that share the same provider + command id | |
| if (!seen.Add((band.ProviderId, commandId))) |
Copilot
AI
Apr 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logging a warning for each duplicate entry inside this loop can spam logs if settings.json already contains duplicates (and SetupBands runs repeatedly). Consider downgrading to Debug/Info or aggregating (log once with a count) to keep this path quieter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because this CAS lambda can now return the original settings when the band is already pinned, the overall PinDockBand call becomes a no-op in that case — but the method still raises CommandsChanged afterwards (outside this hunk). This can trigger unnecessary reload work/UI churn; consider adding a fast-path pre-check before UpdateSettings (while keeping this in-lambda guard) or otherwise only raising CommandsChanged when a pin was actually added.