Skip to content

Conversation

@harisonw
Copy link

@harisonw harisonw commented Jan 30, 2026

Upgrade the project to target .NET Framework 4.8, update NuGet dependencies, and enhance project configuration. Introduce a profile toggle hotkey feature with UI components and state persistence.

Half 'Vibe Coded' as C#/.net is not a stack I've used before - code seems fairly sensible to my uneducated glance though and the feature is working really well from my testing

harisonw and others added 8 commits January 30, 2026 19:24
Upgraded project to target .NET Framework 4.8, updated NuGet packages (CommonServiceLocator, Costura.Fody, Fody), and refreshed .gitignore. Enhanced FodyWeavers.xsd with new options for runtime and unmanaged assemblies. Regenerated designer files with updated tooling. Improved project configuration for modern .NET and Visual Studio compatibility.
Co-authored-by: harisonw <87620631+harisonw@users.noreply.github.com>
Co-authored-by: harisonw <87620631+harisonw@users.noreply.github.com>
Co-authored-by: harisonw <87620631+harisonw@users.noreply.github.com>
Co-authored-by: harisonw <87620631+harisonw@users.noreply.github.com>
Co-authored-by: harisonw <87620631+harisonw@users.noreply.github.com>
Clears focus from the hotkey textbox after setting a profile toggle hotkey to improve user experience. Also adds the System namespace to IVibranceProxy.cs for completeness.
Copilot AI review requested due to automatic review settings January 30, 2026 20:02
@harisonw
Copy link
Author

@juv - cant assign to you

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request upgrades the project from .NET Framework 4.0 to 4.8 and introduces a profile toggle hotkey feature that allows users to temporarily enable/disable profile settings via a global hotkey.

Changes:

  • Upgraded target framework from .NET 4.0 to .NET 4.8 and updated NuGet dependencies (Costura.Fody 4.1.0 → 6.0.0, Fody 6.3.0 → 6.9.3, CommonServiceLocator 1.3 → 2.0.7)
  • Added profile toggle hotkey feature with UI controls, state persistence, and integration into both NVIDIA and AMD vibrance proxy implementations
  • Updated project configuration files and auto-generated designer files to reflect the framework upgrade

Reviewed changes

Copilot reviewed 11 out of 15 changed files in this pull request and generated 48 comments.

Show a summary per file
File Description
vibrance.GUI/vibrance.GUI.csproj Updated target framework to v4.8, upgraded NuGet package references, and modified MSBuild tooling version
vibrance.GUI/packages.config Updated package versions to be compatible with .NET 4.8
vibrance.GUI/App.config Changed supported runtime to .NET Framework 4.8
vibrance.GUI/common/VibranceGUI.cs Added profile toggle hotkey registration, WndProc override, hotkey parsing, and toggle logic with P/Invoke declarations
vibrance.GUI/common/VibranceGUI.Designer.cs Added UI controls for profile toggle feature (checkbox, label, textbox)
vibrance.GUI/common/SettingsController.cs Extended settings persistence to include profile toggle configuration (enabled state, hotkey string, toggle state)
vibrance.GUI/common/ISettingsController.cs Updated interface signatures to include profile toggle parameters
vibrance.GUI/common/IVibranceProxy.cs Added interface methods for profile toggle feature management
vibrance.GUI/common/Definitions.cs Added profile toggle state fields to VibranceInfo struct
vibrance.GUI/NVIDIA/NvidiaDynamicVibranceProxy.cs Implemented profile toggle methods and integrated toggle state check into OnWinEventHook
vibrance.GUI/AMD/AmdDynamicVibranceProxy.cs Implemented profile toggle methods and integrated toggle state check into OnWinEventHook
vibrance.GUI/FodyWeavers.xsd Updated schema to reflect Costura.Fody 6.0.0 capabilities
vibrance.GUI/Properties/Settings.Designer.cs Auto-generated file updated for new framework version
vibrance.GUI/Properties/Resources.Designer.cs Auto-generated file updated for new framework version
.gitignore Added .vs/ directory to gitignore (Visual Studio directory)
Files not reviewed (3)
  • vibrance.GUI/Properties/Resources.Designer.cs: Language not supported
  • vibrance.GUI/Properties/Settings.Designer.cs: Language not supported
  • vibrance.GUI/common/VibranceGUI.Designer.cs: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +528 to +564
private bool TryParseHotkey(string hotkey, out uint modifiers, out uint key)
{
modifiers = 0;
key = 0;
if (string.IsNullOrWhiteSpace(hotkey))
{
return false;
}

string[] parts = hotkey.Split(new[] { '+' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string part in parts)
{
string normalized = part.Trim();
if (string.Equals(normalized, "Ctrl", StringComparison.OrdinalIgnoreCase) ||
string.Equals(normalized, "Control", StringComparison.OrdinalIgnoreCase))
{
modifiers |= HotkeyModControl;
continue;
}
if (string.Equals(normalized, "Alt", StringComparison.OrdinalIgnoreCase))
{
modifiers |= HotkeyModAlt;
continue;
}
if (string.Equals(normalized, "Shift", StringComparison.OrdinalIgnoreCase))
{
modifiers |= HotkeyModShift;
continue;
}

if (Enum.TryParse(normalized, true, out Keys parsedKey))
{
key = (uint)parsedKey;
}
}

return key != 0;
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TryParseHotkey method doesn't properly handle invalid hotkey strings where multiple non-modifier keys appear. If a hotkey string contains multiple keys like "Ctrl+A+B", the method will accept the last valid key ("B") and silently ignore the first one. This could lead to unexpected behavior where the parsed hotkey doesn't match what the user sees in the textbox. Consider validating that only one non-modifier key exists in the string.

Copilot uses AI. Check for mistakes.
}
else
{
_amdAdapter.SetSaturationOnAllDisplays(_vibranceInfo.userVibranceSettingDefault);
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When toggling off the profile, the AMD implementation always calls SetSaturationOnAllDisplays regardless of the affectPrimaryMonitorOnly setting. This is inconsistent with the NVIDIA implementation which respects this setting. The code should check affectPrimaryMonitorOnly and call SetSaturationOnDisplay for the specific screen when that setting is enabled, similar to how the NVIDIA version handles it in lines 414-424 of NvidiaDynamicVibranceProxy.cs.

Suggested change
_amdAdapter.SetSaturationOnAllDisplays(_vibranceInfo.userVibranceSettingDefault);
if (_vibranceInfo.affectPrimaryMonitorOnly && _gameScreen != null && _gameScreen.DeviceName.Equals(screen.DeviceName))
{
_amdAdapter.SetSaturationOnDisplay(_vibranceInfo.userVibranceSettingDefault, _gameScreen.DeviceName);
}
else
{
_amdAdapter.SetSaturationOnAllDisplays(_vibranceInfo.userVibranceSettingDefault);
}

Copilot uses AI. Check for mistakes.
return;
}

_isProfileToggleHotkeyRegistered = RegisterHotKey(this.Handle, ProfileToggleHotkeyId, modifiers, key);
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RegisterHotKey function's return value is stored but never checked for failure. If hotkey registration fails (e.g., because another application is already using that hotkey combination), the user won't receive any feedback. Consider logging a warning or showing a notification when hotkey registration fails.

Suggested change
_isProfileToggleHotkeyRegistered = RegisterHotKey(this.Handle, ProfileToggleHotkeyId, modifiers, key);
bool registrationSucceeded = RegisterHotKey(this.Handle, ProfileToggleHotkeyId, modifiers, key);
_isProfileToggleHotkeyRegistered = registrationSucceeded;
if (!registrationSucceeded)
{
MessageBox.Show(
"Failed to register the profile toggle hotkey. It may already be in use by another application.",
"Hotkey Registration Failed",
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
}

Copilot uses AI. Check for mistakes.
public void SetProfileToggleEnabled(bool profileToggleEnabled)
{
_vibranceInfo.isProfileToggleEnabled = profileToggleEnabled;
_vibranceInfo.isProfileToggleOn = true;
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SetProfileToggleEnabled unconditionally resets isProfileToggleOn to true. This could override the user's saved toggle state when disabling and re-enabling the feature, or when changing settings. The state should only be reset when the feature is being disabled, not when it's being enabled.

Suggested change
_vibranceInfo.isProfileToggleOn = true;
if (!profileToggleEnabled)
{
_vibranceInfo.isProfileToggleOn = true;
}

Copilot uses AI. Check for mistakes.
public void SetProfileToggleEnabled(bool profileToggleEnabled)
{
_vibranceInfo.isProfileToggleEnabled = profileToggleEnabled;
_vibranceInfo.isProfileToggleOn = true;
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SetProfileToggleEnabled unconditionally resets isProfileToggleOn to true. This could override the user's saved toggle state when disabling and re-enabling the feature, or when changing settings. The state should only be reset when the feature is being disabled, not when it's being enabled.

Suggested change
_vibranceInfo.isProfileToggleOn = true;
if (!profileToggleEnabled)
{
_vibranceInfo.isProfileToggleOn = true;
}

Copilot uses AI. Check for mistakes.
_vibranceInfo.displayHandles.ForEach(handle => setDVCLevel(handle, _vibranceInfo.userVibranceSettingDefault));
}

if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == true)
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expression 'A == true' can be simplified to 'A'.

Copilot uses AI. Check for mistakes.

//test if color settings change is needed
if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false &&
if (shouldApplyProfileSettings && _vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false &&
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expression 'A == false' can be simplified to '!A'.

Copilot uses AI. Check for mistakes.
Comment on lines +405 to +406
if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false &&
DeviceGammaRampHelper.IsGammaRampEqualToWindowsValues(_vibranceInfo, applicationSetting) == false)
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expression 'A == false' can be simplified to '!A'.

Suggested change
if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false &&
DeviceGammaRampHelper.IsGammaRampEqualToWindowsValues(_vibranceInfo, applicationSetting) == false)
if (!_vibranceInfo.neverChangeColorSettings && !_vibranceInfo.isColorSettingApplied &&
!DeviceGammaRampHelper.IsGammaRampEqualToWindowsValues(_vibranceInfo, applicationSetting))

Copilot uses AI. Check for mistakes.
setDVCLevel(_vibranceInfo.defaultHandle, applicationSetting.IngameLevel);
}

if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false &&
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expression 'A == false' can be simplified to '!A'.

Copilot uses AI. Check for mistakes.

//test if color settings change is needed
if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false &&
if (shouldApplyProfileSettings && _vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false &&
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expression 'A == false' can be simplified to '!A'.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant