2
0

Add port config, quick-switch toolbar, and dark mode styling

- Add Config button to each monitor for hiding ports, custom labels, and quick-switch selection
- Add quick-switch toolbar at top of popup for one-click input switching
- Add dark mode styling for all controls (buttons, combobox, dropdown items)
- Add loading spinner animation
- Add Exit button in header
- Fix dropdown selection to correctly show current input

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-04 00:25:01 -05:00
parent f23f26d809
commit 2a3a502567
6 changed files with 756 additions and 28 deletions

View File

@@ -0,0 +1,125 @@
using CMM.Library.Helpers;
using CMM.Library.ViewModel;
using System.IO;
namespace CMM.Library.Config;
public static class MonitorConfigManager
{
private static readonly string ConfigFolder = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"MonitorControl");
private static readonly string ConfigFile = Path.Combine(ConfigFolder, "config.json");
private static AppConfig? _cachedConfig;
public static AppConfig Load()
{
if (_cachedConfig != null)
return _cachedConfig;
if (!File.Exists(ConfigFile))
{
_cachedConfig = new AppConfig();
return _cachedConfig;
}
try
{
_cachedConfig = ConfigFile.JsonFormFile<AppConfig>() ?? new AppConfig();
}
catch
{
_cachedConfig = new AppConfig();
}
return _cachedConfig;
}
public static void Save(AppConfig config)
{
_cachedConfig = config;
config.FileToJson(ConfigFile);
}
public static MonitorConfig GetMonitorConfig(string serialNumber)
{
var config = Load();
return config.Monitors.FirstOrDefault(m => m.SerialNumber == serialNumber)
?? new MonitorConfig { SerialNumber = serialNumber };
}
public static void SaveMonitorConfig(MonitorConfig monitorConfig)
{
var config = Load();
var existing = config.Monitors.FirstOrDefault(m => m.SerialNumber == monitorConfig.SerialNumber);
if (existing != null)
config.Monitors.Remove(existing);
config.Monitors.Add(monitorConfig);
Save(config);
}
public static List<QuickSwitchItem> GetQuickSwitchItems()
{
var config = Load();
var items = new List<QuickSwitchItem>();
foreach (var monitor in config.Monitors)
{
foreach (var port in monitor.Ports.Where(p => p.ShowInQuickSwitch && !p.IsHidden))
{
items.Add(new QuickSwitchItem
{
MonitorSerialNumber = monitor.SerialNumber,
MonitorName = monitor.MonitorName,
PortVcpValue = port.VcpValue,
PortLabel = port.DisplayName
});
}
}
return items;
}
public static List<InputSourceOption> ApplyConfigToOptions(
string serialNumber,
List<InputSourceOption> options)
{
var monitorConfig = GetMonitorConfig(serialNumber);
if (monitorConfig.Ports.Count == 0)
return options;
var result = new List<InputSourceOption>();
foreach (var option in options)
{
var portConfig = monitorConfig.Ports.FirstOrDefault(p => p.VcpValue == option.Value);
if (portConfig != null)
{
// Respect hidden setting - don't show hidden ports
if (portConfig.IsHidden)
continue;
if (!string.IsNullOrWhiteSpace(portConfig.CustomLabel))
{
result.Add(new InputSourceOption(option.Value, portConfig.CustomLabel));
continue;
}
}
result.Add(option);
}
return result;
}
public static void ClearCache()
{
_cachedConfig = null;
}
}

View File

@@ -0,0 +1,44 @@
namespace CMM.Library.ViewModel;
/// <summary>
/// Configuration for a single monitor's ports
/// </summary>
public class MonitorConfig
{
public string SerialNumber { get; set; } = string.Empty;
public string MonitorName { get; set; } = string.Empty;
public List<PortConfig> Ports { get; set; } = new();
}
/// <summary>
/// Configuration for a single input port
/// </summary>
public class PortConfig
{
public int VcpValue { get; set; }
public string DefaultName { get; set; } = string.Empty;
public string CustomLabel { get; set; } = string.Empty;
public bool IsHidden { get; set; }
public bool ShowInQuickSwitch { get; set; }
public string DisplayName => string.IsNullOrWhiteSpace(CustomLabel) ? DefaultName : CustomLabel;
}
/// <summary>
/// Quick switch item shown in toolbar
/// </summary>
public class QuickSwitchItem
{
public string MonitorSerialNumber { get; set; } = string.Empty;
public string MonitorName { get; set; } = string.Empty;
public int PortVcpValue { get; set; }
public string PortLabel { get; set; } = string.Empty;
}
/// <summary>
/// Root configuration object
/// </summary>
public class AppConfig
{
public List<MonitorConfig> Monitors { get; set; } = new();
}