Refactor MonitorStateManager and MainViewModel to use HardwareId for stable identification; update logging for clarity and consistency.

This commit is contained in:
Yu Leng (from Dev Box)
2025-10-17 18:03:13 +08:00
parent c2d82a72ca
commit bda629c70a
2 changed files with 44 additions and 28 deletions

View File

@@ -71,6 +71,8 @@ namespace PowerDisplay.Helpers
/// <summary> /// <summary>
/// Serializable state for JSON persistence /// Serializable state for JSON persistence
/// Dictionary key should be HardwareId (e.g., "GSM5C6D") for stable identification
/// Legacy files may have used InternalName (e.g., "DISPLAY1_0_3") which will still load but won't match after reconnection
/// </summary> /// </summary>
private sealed class MonitorStateFile private sealed class MonitorStateFile
{ {
@@ -116,13 +118,20 @@ namespace PowerDisplay.Helpers
/// <summary> /// <summary>
/// Update monitor parameter in memory (lock-free, non-blocking) /// Update monitor parameter in memory (lock-free, non-blocking)
/// Uses HardwareId as the stable key
/// </summary> /// </summary>
public void UpdateMonitorParameter(string monitorId, string property, int value) public void UpdateMonitorParameter(string hardwareId, string property, int value)
{ {
try try
{ {
// Get or create parameter entry if (string.IsNullOrEmpty(hardwareId))
var parameters = _parameters.GetOrAdd(monitorId, _ => new MonitorParameters()); {
Logger.LogWarning($"Cannot update monitor parameter: HardwareId is empty");
return;
}
// Get or create parameter entry using HardwareId
var parameters = _parameters.GetOrAdd(hardwareId, _ => new MonitorParameters());
// Update the specific property (volatile write) // Update the specific property (volatile write)
switch (property) switch (property)
@@ -147,7 +156,7 @@ namespace PowerDisplay.Helpers
// Mark as dirty (will be saved in next timer cycle) // Mark as dirty (will be saved in next timer cycle)
_isDirty = true; _isDirty = true;
Logger.LogTrace($"[State] Updated {property}={value} for monitor '{monitorId}'"); Logger.LogTrace($"[State] Updated {property}={value} for monitor HardwareId='{hardwareId}'");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -156,11 +165,16 @@ namespace PowerDisplay.Helpers
} }
/// <summary> /// <summary>
/// Get saved parameters for a monitor /// Get saved parameters for a monitor using HardwareId
/// </summary> /// </summary>
public (int Brightness, int ColorTemperature, int Contrast, int Volume)? GetMonitorParameters(string monitorId) public (int Brightness, int ColorTemperature, int Contrast, int Volume)? GetMonitorParameters(string hardwareId)
{ {
if (_parameters.TryGetValue(monitorId, out var parameters)) if (string.IsNullOrEmpty(hardwareId))
{
return null;
}
if (_parameters.TryGetValue(hardwareId, out var parameters))
{ {
return (parameters.Brightness, parameters.ColorTemperature, parameters.Contrast, parameters.Volume); return (parameters.Brightness, parameters.ColorTemperature, parameters.Contrast, parameters.Volume);
} }
@@ -168,11 +182,11 @@ namespace PowerDisplay.Helpers
} }
/// <summary> /// <summary>
/// Check if state exists for a monitor /// Check if state exists for a monitor (by HardwareId)
/// </summary> /// </summary>
public bool HasMonitorState(string monitorId) public bool HasMonitorState(string hardwareId)
{ {
return _parameters.ContainsKey(monitorId); return !string.IsNullOrEmpty(hardwareId) && _parameters.ContainsKey(hardwareId);
} }
/// <summary> /// <summary>
@@ -195,10 +209,10 @@ namespace PowerDisplay.Helpers
{ {
foreach (var kvp in state.Monitors) foreach (var kvp in state.Monitors)
{ {
var monitorId = kvp.Key; var monitorKey = kvp.Key; // Should be HardwareId (e.g., "GSM5C6D")
var entry = kvp.Value; var entry = kvp.Value;
var parameters = _parameters.GetOrAdd(monitorId, _ => new MonitorParameters()); var parameters = _parameters.GetOrAdd(monitorKey, _ => new MonitorParameters());
parameters.Brightness = entry.Brightness; parameters.Brightness = entry.Brightness;
parameters.ColorTemperature = entry.ColorTemperature; parameters.ColorTemperature = entry.ColorTemperature;
parameters.Contrast = entry.Contrast; parameters.Contrast = entry.Contrast;
@@ -206,6 +220,7 @@ namespace PowerDisplay.Helpers
} }
Logger.LogInfo($"[State] Loaded state for {state.Monitors.Count} monitors from {_stateFilePath}"); Logger.LogInfo($"[State] Loaded state for {state.Monitors.Count} monitors from {_stateFilePath}");
Logger.LogInfo($"[State] Monitor keys in state file: {string.Join(", ", state.Monitors.Keys)}");
} }
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -487,14 +487,14 @@ public class MainViewModel : INotifyPropertyChanged, IDisposable
foreach (var monitorVm in Monitors) foreach (var monitorVm in Monitors)
{ {
var internalName = GetInternalName(monitorVm); var hardwareId = monitorVm.HardwareId;
Logger.LogInfo($"[Startup] Processing monitor: '{monitorVm.Name}', InternalName: '{internalName}'"); Logger.LogInfo($"[Startup] Processing monitor: '{monitorVm.Name}', HardwareId: '{hardwareId}'");
// Find and apply corresponding saved settings from state file // Find and apply corresponding saved settings from state file using stable HardwareId
var savedState = _stateManager.GetMonitorParameters(internalName); var savedState = _stateManager.GetMonitorParameters(hardwareId);
if (savedState.HasValue) if (savedState.HasValue)
{ {
Logger.LogInfo($"[Startup] Restoring state for '{internalName}': Brightness={savedState.Value.Brightness}, ColorTemp={savedState.Value.ColorTemperature}"); Logger.LogInfo($"[Startup] Restoring state for HardwareId '{hardwareId}': Brightness={savedState.Value.Brightness}, ColorTemp={savedState.Value.ColorTemperature}");
// 验证并应用保存的值(跳过无效值) // 验证并应用保存的值(跳过无效值)
if (savedState.Value.Brightness >= monitorVm.MinBrightness && savedState.Value.Brightness <= monitorVm.MaxBrightness) if (savedState.Value.Brightness >= monitorVm.MinBrightness && savedState.Value.Brightness <= monitorVm.MaxBrightness)
@@ -503,7 +503,7 @@ public class MainViewModel : INotifyPropertyChanged, IDisposable
} }
else else
{ {
Logger.LogWarning($"[Startup] Invalid brightness value {savedState.Value.Brightness} for '{internalName}', skipping"); Logger.LogWarning($"[Startup] Invalid brightness value {savedState.Value.Brightness} for HardwareId '{hardwareId}', skipping");
} }
// 色温值必须有效且在范围内 // 色温值必须有效且在范围内
@@ -515,7 +515,7 @@ public class MainViewModel : INotifyPropertyChanged, IDisposable
} }
else else
{ {
Logger.LogWarning($"[Startup] Invalid color temperature value {savedState.Value.ColorTemperature} for '{internalName}', skipping"); Logger.LogWarning($"[Startup] Invalid color temperature value {savedState.Value.ColorTemperature} for HardwareId '{hardwareId}', skipping");
} }
// 对比度值验证 - 只在硬件支持的情况下才应用 // 对比度值验证 - 只在硬件支持的情况下才应用
@@ -527,7 +527,7 @@ public class MainViewModel : INotifyPropertyChanged, IDisposable
} }
else if (!monitorVm.ShowContrast) else if (!monitorVm.ShowContrast)
{ {
Logger.LogInfo($"[Startup] Contrast not supported on '{internalName}', skipping"); Logger.LogInfo($"[Startup] Contrast not supported on HardwareId '{hardwareId}', skipping");
} }
// 音量值验证 - 只在硬件支持的情况下才应用 // 音量值验证 - 只在硬件支持的情况下才应用
@@ -539,15 +539,16 @@ public class MainViewModel : INotifyPropertyChanged, IDisposable
} }
else if (!monitorVm.ShowVolume) else if (!monitorVm.ShowVolume)
{ {
Logger.LogInfo($"[Startup] Volume not supported on '{internalName}', skipping"); Logger.LogInfo($"[Startup] Volume not supported on HardwareId '{hardwareId}', skipping");
} }
} }
else else
{ {
Logger.LogInfo($"[Startup] No saved state for '{internalName}' - keeping current hardware values"); Logger.LogInfo($"[Startup] No saved state for HardwareId '{hardwareId}' - keeping current hardware values");
} }
// Apply feature visibility settings // Apply feature visibility settings (still need InternalName for Settings UI matching)
var internalName = GetInternalName(monitorVm);
ApplyFeatureVisibility(monitorVm, settings, internalName); ApplyFeatureVisibility(monitorVm, settings, internalName);
} }
@@ -634,7 +635,7 @@ public class MainViewModel : INotifyPropertyChanged, IDisposable
{ {
try try
{ {
// Find the monitor VM to get the converted internal name // Find the monitor VM to get the stable HardwareId
var monitorVm = GetMonitorViewModel(monitorId); var monitorVm = GetMonitorViewModel(monitorId);
if (monitorVm == null) if (monitorVm == null)
{ {
@@ -642,13 +643,13 @@ public class MainViewModel : INotifyPropertyChanged, IDisposable
return; return;
} }
// Use converted internal name for consistency with Settings UI // Use stable HardwareId as the key for state persistence
var internalName = GetInternalName(monitorVm); var hardwareId = monitorVm.HardwareId;
// Update parameter in state file (lock-free, non-blocking) // Update parameter in state file (lock-free, non-blocking)
_stateManager.UpdateMonitorParameter(internalName, property, value); _stateManager.UpdateMonitorParameter(hardwareId, property, value);
Logger.LogTrace($"[State] Queued setting change for '{internalName}': {property}={value}"); Logger.LogTrace($"[State] Queued setting change for HardwareId '{hardwareId}': {property}={value}");
} }
catch (Exception ex) catch (Exception ex)
{ {