mirror of
https://github.com/Raphire/Win11Debloat.git
synced 2026-06-10 10:36:26 +00:00
947 lines
44 KiB
PowerShell
947 lines
44 KiB
PowerShell
function Show-MainWindow {
|
|
Add-Type -AssemblyName PresentationFramework,PresentationCore,WindowsBase,System.Windows.Forms | Out-Null
|
|
|
|
# ---- Constrain maximized window to taskbar work area ----
|
|
if (-not ([System.Management.Automation.PSTypeName]'Win11Debloat.MaximizedWindowHelper').Type) {
|
|
Add-Type -Namespace Win11Debloat -Name MaximizedWindowHelper `
|
|
-ReferencedAssemblies 'PresentationFramework','System.Windows.Forms','System.Drawing' `
|
|
-MemberDefinition @'
|
|
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
|
|
private struct MINMAXINFO {
|
|
public POINT ptReserved, ptMaxSize, ptMaxPosition, ptMinTrackSize, ptMaxTrackSize;
|
|
}
|
|
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
|
|
private struct POINT { public int x, y; }
|
|
|
|
[System.Runtime.InteropServices.DllImport("user32.dll")]
|
|
private static extern System.IntPtr MonitorFromWindow(System.IntPtr hwnd, uint dwFlags);
|
|
|
|
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
|
|
private static extern bool GetMonitorInfo(System.IntPtr hMonitor, ref MONITORINFO lpmi);
|
|
|
|
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
|
|
private struct RECT {
|
|
public int Left, Top, Right, Bottom;
|
|
}
|
|
|
|
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
|
|
private struct MONITORINFO {
|
|
public int cbSize;
|
|
public RECT rcMonitor;
|
|
public RECT rcWork;
|
|
public uint dwFlags;
|
|
}
|
|
|
|
public static System.IntPtr WmGetMinMaxInfoHook(
|
|
System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) {
|
|
if (msg == 0x0024) { // WM_GETMINMAXINFO
|
|
var mmi = (MINMAXINFO)System.Runtime.InteropServices.Marshal.PtrToStructure(
|
|
lParam, typeof(MINMAXINFO));
|
|
|
|
const uint MONITOR_DEFAULTTONEAREST = 0x00000002;
|
|
var monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
|
|
var monitorInfo = new MONITORINFO();
|
|
monitorInfo.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(MONITORINFO));
|
|
|
|
if (monitor != System.IntPtr.Zero && GetMonitorInfo(monitor, ref monitorInfo)) {
|
|
mmi.ptMaxPosition.x = monitorInfo.rcWork.Left - monitorInfo.rcMonitor.Left;
|
|
mmi.ptMaxPosition.y = monitorInfo.rcWork.Top - monitorInfo.rcMonitor.Top;
|
|
mmi.ptMaxSize.x = monitorInfo.rcWork.Right - monitorInfo.rcWork.Left;
|
|
mmi.ptMaxSize.y = monitorInfo.rcWork.Bottom - monitorInfo.rcWork.Top;
|
|
}
|
|
else {
|
|
var screen = System.Windows.Forms.Screen.FromHandle(hwnd);
|
|
var wa = screen.WorkingArea;
|
|
var bounds = screen.Bounds;
|
|
mmi.ptMaxPosition.x = wa.Left - bounds.Left;
|
|
mmi.ptMaxPosition.y = wa.Top - bounds.Top;
|
|
mmi.ptMaxSize.x = wa.Width;
|
|
mmi.ptMaxSize.y = wa.Height;
|
|
}
|
|
|
|
System.Runtime.InteropServices.Marshal.StructureToPtr(mmi, lParam, true);
|
|
}
|
|
return System.IntPtr.Zero;
|
|
}
|
|
'@
|
|
}
|
|
|
|
$WinVersion = Get-ItemPropertyValue 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' CurrentBuild
|
|
$usesDarkMode = GetSystemUsesDarkMode
|
|
|
|
# ---- Load XAML ----
|
|
$xaml = Get-Content -Path $script:MainWindowSchema -Raw
|
|
$reader = [System.Xml.XmlReader]::Create([System.IO.StringReader]::new($xaml))
|
|
try {
|
|
$window = [System.Windows.Markup.XamlReader]::Load($reader)
|
|
}
|
|
finally {
|
|
$reader.Close()
|
|
}
|
|
|
|
SetWindowThemeResources -window $window -usesDarkMode $usesDarkMode
|
|
|
|
$mainBorder = $window.FindName('MainBorder')
|
|
$titleBarBackground = $window.FindName('TitleBarBackground')
|
|
$kofiBtn = $window.FindName('KofiBtn')
|
|
$menuBtn = $window.FindName('MenuBtn')
|
|
$closeBtn = $window.FindName('CloseBtn')
|
|
$menuDocumentation = $window.FindName('MenuDocumentation')
|
|
$menuReportBug = $window.FindName('MenuReportBug')
|
|
$menuLogs = $window.FindName('MenuLogs')
|
|
$menuAbout = $window.FindName('MenuAbout')
|
|
$importConfigBtn = $window.FindName('ImportConfigBtn')
|
|
$exportConfigBtn = $window.FindName('ExportConfigBtn')
|
|
$restoreBackupBtn = $window.FindName('RestoreBackupBtn')
|
|
$homeContentPanel = $window.FindName('HomeContentPanel')
|
|
$contentGrid = $window.FindName('ContentGrid')
|
|
$maxContentWidth = 1600.0
|
|
|
|
$windowStateNormal = [System.Windows.WindowState]::Normal
|
|
$windowStateMaximized = [System.Windows.WindowState]::Maximized
|
|
$normalWindowShadow = $mainBorder.Effect
|
|
$initialNormalMaxWidth = 1400.0
|
|
|
|
$script:MainWindow = $window
|
|
$script:GuiWindow = $window
|
|
|
|
# ---- Handle unhandled exceptions on the dispatcher thread ----
|
|
[System.Windows.Threading.Dispatcher]::CurrentDispatcher.Add_UnhandledException({
|
|
param($sender, $e)
|
|
Write-Warning "Unhandled exception in GUI: $($e.Exception.Message)"
|
|
Write-Warning "Stack trace: $($e.Exception.StackTrace)"
|
|
$e.Handled = $true
|
|
})
|
|
|
|
# ---- Window chrome helpers ----
|
|
$updateWindowChrome = { Update-MainWindowChrome -Window $window -MainBorder $mainBorder -TitleBarBackground $titleBarBackground -NormalWindowShadow $normalWindowShadow }
|
|
$applyInitialWindowSize = { Set-MainWindowInitialSize -Window $window -InitialNormalMaxWidth $initialNormalMaxWidth }
|
|
$updateContentMargin = { Update-MainWindowContentMargin -Window $window -ContentGrid $contentGrid -MaxContentWidth $maxContentWidth }
|
|
$updateHomeContentPosition = { Update-MainWindowHomeContentPosition -Window $window -HomeContentPanel $homeContentPanel }
|
|
|
|
# ---- Window chrome event wiring ----
|
|
$window.Add_SourceInitialized({
|
|
& $applyInitialWindowSize
|
|
& $updateWindowChrome
|
|
|
|
$hwndHelper = New-Object System.Windows.Interop.WindowInteropHelper($window)
|
|
$hwndSource = [System.Windows.Interop.HwndSource]::FromHwnd($hwndHelper.Handle)
|
|
$hookMethod = [Win11Debloat.MaximizedWindowHelper].GetMethod('WmGetMinMaxInfoHook')
|
|
$hook = [System.Delegate]::CreateDelegate([System.Windows.Interop.HwndSourceHook], $hookMethod)
|
|
$hwndSource.AddHook($hook)
|
|
})
|
|
|
|
$window.Add_SizeChanged({
|
|
& $updateContentMargin
|
|
& $updateHomeContentPosition
|
|
Update-TweaksResponsiveColumns -Window $window
|
|
})
|
|
|
|
$window.Add_StateChanged({ & $updateWindowChrome })
|
|
|
|
$window.Add_LocationChanged({
|
|
if ($script:BubblePopup -and $script:BubblePopup.IsOpen) {
|
|
$script:BubblePopup.HorizontalOffset += 1
|
|
$script:BubblePopup.HorizontalOffset -= 1
|
|
}
|
|
})
|
|
|
|
# ---- Menu/button event wiring ----
|
|
$kofiBtn.Add_Click({ Start-Process "https://ko-fi.com/raphire" })
|
|
|
|
$menuBtn.Add_Click({
|
|
$menuBtn.ContextMenu.PlacementTarget = $menuBtn
|
|
$menuBtn.ContextMenu.Placement = [System.Windows.Controls.Primitives.PlacementMode]::Bottom
|
|
$menuBtn.ContextMenu.IsOpen = $true
|
|
})
|
|
|
|
$menuDocumentation.Add_Click({ Start-Process "https://github.com/Raphire/Win11Debloat/wiki" })
|
|
$menuReportBug.Add_Click({ Start-Process "https://github.com/Raphire/Win11Debloat/issues" })
|
|
|
|
$menuLogs.Add_Click({
|
|
$logsFolder = Join-Path (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent) 'Logs'
|
|
if (Test-Path $logsFolder) {
|
|
Start-Process "explorer.exe" -ArgumentList $logsFolder
|
|
}
|
|
else {
|
|
Show-MessageBox -Message "No logs folder found at: $logsFolder" -Title "Logs" -Button 'OK' -Icon 'Information'
|
|
}
|
|
})
|
|
|
|
$menuAbout.Add_Click({ Show-AboutDialog -Owner $window })
|
|
|
|
$closeBtn.Add_Click({ $window.Close() })
|
|
$window.Add_Closing({ $script:CancelRequested = $true })
|
|
|
|
# ---- App Selection panel elements ----
|
|
$appsPanel = $window.FindName('AppSelectionPanel')
|
|
$onlyInstalledAppsBox = $window.FindName('OnlyInstalledAppsBox')
|
|
$loadingAppsIndicator = $window.FindName('LoadingAppsIndicator')
|
|
$appSelectionStatus = $window.FindName('AppSelectionStatus')
|
|
$headerNameBtn = $window.FindName('HeaderNameBtn')
|
|
$headerDescriptionBtn = $window.FindName('HeaderDescriptionBtn')
|
|
$headerAppIdBtn = $window.FindName('HeaderAppIdBtn')
|
|
$sortArrowName = $window.FindName('SortArrowName')
|
|
$sortArrowDescription = $window.FindName('SortArrowDescription')
|
|
$sortArrowAppId = $window.FindName('SortArrowAppId')
|
|
$presetsBtn = $window.FindName('PresetsBtn')
|
|
$presetsPopup = $window.FindName('PresetsPopup')
|
|
$presetDefaultApps = $window.FindName('PresetDefaultApps')
|
|
$presetLastUsed = $window.FindName('PresetLastUsed')
|
|
$jsonPresetsPanel = $window.FindName('JsonPresetsPanel')
|
|
$presetsArrow = $window.FindName('PresetsArrow')
|
|
$clearAppSelectionBtn = $window.FindName('ClearAppSelectionBtn')
|
|
$tweaksPresetsBtn = $window.FindName('TweaksPresetsBtn')
|
|
$tweaksPresetsPopup = $window.FindName('TweaksPresetsPopup')
|
|
$presetDefaultTweaksBtn = $window.FindName('PresetDefaultTweaksBtn')
|
|
$presetLastUsedTweaksBtn = $window.FindName('PresetLastUsedTweaksBtn')
|
|
$presetPrivacyTweaksBtn = $window.FindName('PresetPrivacyTweaksBtn')
|
|
$presetAITweaksBtn = $window.FindName('PresetAITweaksBtn')
|
|
$tweaksPresetsArrow = $window.FindName('TweaksPresetsArrow')
|
|
|
|
# ---- Navigation elements ----
|
|
$tabControl = $window.FindName('MainTabControl')
|
|
$previousBtn = $window.FindName('PreviousBtn')
|
|
$nextBtn = $window.FindName('NextBtn')
|
|
$userSelectionCombo = $window.FindName('UserSelectionCombo')
|
|
$userSelectionDescription = $window.FindName('UserSelectionDescription')
|
|
$otherUserPanel = $window.FindName('OtherUserPanel')
|
|
$otherUsernameTextBox = $window.FindName('OtherUsernameTextBox')
|
|
$usernameTextBoxPlaceholder = $window.FindName('UsernameTextBoxPlaceholder')
|
|
$usernameValidationMessage = $window.FindName('UsernameValidationMessage')
|
|
$appRemovalScopeCombo = $window.FindName('AppRemovalScopeCombo')
|
|
$appRemovalScopeDescription = $window.FindName('AppRemovalScopeDescription')
|
|
$appRemovalScopeSection = $window.FindName('AppRemovalScopeSection')
|
|
$appRemovalScopeCurrentUser = $window.FindName('AppRemovalScopeCurrentUser')
|
|
$appRemovalScopeTargetUser = $window.FindName('AppRemovalScopeTargetUser')
|
|
|
|
# ---- Tweak search elements ----
|
|
$tweakSearchBox = $window.FindName('TweakSearchBox')
|
|
$tweakSearchPlaceholder = $window.FindName('TweakSearchPlaceholder')
|
|
$tweakSearchBorder = $window.FindName('TweakSearchBorder')
|
|
$tweaksScrollViewer = $window.FindName('TweaksScrollViewer')
|
|
$tweaksGrid = $window.FindName('TweaksGrid')
|
|
$ShowCurrentlyAppliedTweaksCheckBox = $window.FindName('ShowCurrentlyAppliedTweaksCheckBox')
|
|
$clearAllTweaksBtn = $window.FindName('ClearAllTweaksBtn')
|
|
|
|
# ---- Deployment elements ----
|
|
$reviewChangesBtn = $window.FindName('ReviewChangesBtn')
|
|
$deploymentApplyBtn = $window.FindName('DeploymentApplyBtn')
|
|
$homeStartBtn = $window.FindName('HomeStartBtn')
|
|
$homeDefaultModeBtn = $window.FindName('HomeDefaultModeBtn')
|
|
|
|
# ---- Wire export/import ----
|
|
$exportConfigBtn.Add_Click({
|
|
try {
|
|
Export-Configuration -Owner $window -UsesDarkMode $usesDarkMode -AppsPanel $appsPanel -UiControlMappings $script:UiControlMappings -UserSelectionCombo $userSelectionCombo -OtherUsernameTextBox $otherUsernameTextBox
|
|
}
|
|
catch {
|
|
Write-Warning "Export configuration failed: $($_.Exception.Message)"
|
|
Show-MessageBox -Owner $window -Message "Unable to open export configuration dialog: $($_.Exception.Message)" -Title 'Export Configuration Failed' -Button 'OK' -Icon 'Error' | Out-Null
|
|
}
|
|
})
|
|
|
|
$importConfigBtn.Add_Click({
|
|
try {
|
|
Import-Configuration -Owner $window -UsesDarkMode $usesDarkMode -AppsPanel $appsPanel -UiControlMappings $script:UiControlMappings -UserSelectionCombo $userSelectionCombo -OtherUsernameTextBox $otherUsernameTextBox -OnAppsImported { Update-AppSelectionStatus -AppsPanel $appsPanel -AppSelectionStatus $appSelectionStatus -AppRemovalScopeCombo $appRemovalScopeCombo -AppRemovalScopeSection $appRemovalScopeSection -AppRemovalScopeDescription $appRemovalScopeDescription -UserSelectionCombo $userSelectionCombo; Update-AppPresetStates -AppsPanel $appsPanel } -OnImportCompleted {
|
|
$tabControl.SelectedIndex = 3
|
|
Update-NavigationButtons -Window $window -TabControl $tabControl
|
|
$window.Dispatcher.BeginInvoke([System.Windows.Threading.DispatcherPriority]::Loaded, [action]{
|
|
Show-Bubble -TargetControl $reviewChangesBtn -Message 'View the selected changes here'
|
|
}) | Out-Null
|
|
}
|
|
}
|
|
catch {
|
|
Write-Warning "Import configuration failed: $($_.Exception.Message)"
|
|
Show-MessageBox -Owner $window -Message "Unable to open import configuration dialog: $($_.Exception.Message)" -Title 'Import Configuration Failed' -Button 'OK' -Icon 'Error' | Out-Null
|
|
}
|
|
})
|
|
|
|
# ---- Restore backup ----
|
|
if ($restoreBackupBtn) {
|
|
$restoreBackupBtn.Add_Click({
|
|
try {
|
|
$restoreResult = Show-RestoreBackupWindow -Owner $window
|
|
if ($restoreResult -and $restoreResult.RestoredRegistry -eq $true) {
|
|
Update-CurrentTweakSystemState -Window $window -ApplyToUi:$false
|
|
|
|
if ($ShowCurrentlyAppliedTweaksCheckBox -and $ShowCurrentlyAppliedTweaksCheckBox.IsChecked -eq $true) {
|
|
Reset-TweaksToSystemState -Window $window -LoadSystemState $true
|
|
Update-TweakPresetStates -Window $window
|
|
}
|
|
}
|
|
}
|
|
catch {
|
|
Write-Warning "Restore backup action failed: $($_.Exception.Message)"
|
|
Show-MessageBox -Owner $window -Message "Unable to open restore backup dialog: $($_.Exception.Message)" -Title 'Restore Backup Failed' -Button 'OK' -Icon 'Error' | Out-Null
|
|
}
|
|
})
|
|
}
|
|
|
|
# ---- Script-level state initialization ----
|
|
$script:MainWindowLastSelectedCheckbox = $null
|
|
$script:IsLoadingApps = $false
|
|
$script:PendingDefaultMode = $false
|
|
$script:PreloadedAppData = $null
|
|
$script:UpdatingPresets = $false
|
|
$script:UpdatingTweakPresets = $false
|
|
$script:SortColumn = 'Name'
|
|
$script:SortAscending = $true
|
|
$script:AppSearchMatches = @()
|
|
$script:AppSearchMatchIndex = -1
|
|
$script:JsonPresetCheckboxes = @()
|
|
|
|
if ($importConfigBtn) { $importConfigBtn.IsEnabled = $false }
|
|
|
|
# ---- Build JSON-defined app presets ----
|
|
foreach ($preset in (LoadAppPresetsFromJson)) {
|
|
$checkbox = New-Object System.Windows.Controls.CheckBox
|
|
$checkbox.Content = $preset.Name
|
|
$checkbox.IsThreeState = $true
|
|
$checkbox.Style = $window.Resources['PresetCheckBoxStyle']
|
|
$checkbox.ToolTip = "Select $($preset.Name)"
|
|
$checkbox.SetValue([System.Windows.Automation.AutomationProperties]::NameProperty, $preset.Name)
|
|
Add-TriStateClickBehavior -CheckBox $checkbox
|
|
Add-Member -InputObject $checkbox -MemberType NoteProperty -Name 'PresetAppIds' -Value $preset.AppIds
|
|
$jsonPresetsPanel.Children.Add($checkbox) | Out-Null
|
|
$script:JsonPresetCheckboxes += $checkbox
|
|
|
|
$checkbox.Add_Click({
|
|
if ($script:UpdatingPresets) { return }
|
|
$presetIds = $this.PresetAppIds
|
|
$check = ConvertTo-NormalizedCheckboxState -CheckBox $this
|
|
Invoke-AppPreset -AppsPanel $appsPanel -MatchFilter { param($c) (@($c.AppIds) | Where-Object { $presetIds -contains $_ }).Count -gt 0 }.GetNewClosure() -Check $check
|
|
})
|
|
}
|
|
|
|
# ---- App sort helpers ----
|
|
$updateSortArrows = {
|
|
Update-SortArrows `
|
|
-SortArrowName $sortArrowName -SortArrowDescription $sortArrowDescription -SortArrowAppId $sortArrowAppId
|
|
}
|
|
|
|
$rebuildAppSearchIndex = {
|
|
param($activeMatch = $null)
|
|
Update-AppsPanelRebuildSearchIndex -AppsPanel $appsPanel -ActiveMatch $activeMatch
|
|
}
|
|
|
|
$sortApps = {
|
|
Update-AppsPanelSort -AppsPanel $appsPanel `
|
|
-SortArrowName $sortArrowName -SortArrowDescription $sortArrowDescription -SortArrowAppId $sortArrowAppId
|
|
if ($script:AppSearchMatches.Count -gt 0) {
|
|
$activeMatch = if ($script:AppSearchMatchIndex -ge 0 -and $script:AppSearchMatchIndex -lt $script:AppSearchMatches.Count) {
|
|
$script:AppSearchMatches[$script:AppSearchMatchIndex]
|
|
} else { $null }
|
|
& $rebuildAppSearchIndex -activeMatch $activeMatch
|
|
}
|
|
}
|
|
|
|
$setSortColumn = {
|
|
param($column)
|
|
if ($script:SortColumn -eq $column) {
|
|
$script:SortAscending = -not $script:SortAscending
|
|
}
|
|
else {
|
|
$script:SortColumn = $column
|
|
$script:SortAscending = $true
|
|
}
|
|
& $sortApps
|
|
}
|
|
|
|
# ---- Tri-state preset wiring for app presets ----
|
|
foreach ($presetCheckBox in @($presetDefaultApps, $presetLastUsed)) {
|
|
Add-TriStateClickBehavior -CheckBox $presetCheckBox
|
|
}
|
|
|
|
# ---- Preset: Default selection ----
|
|
$presetDefaultApps.Add_Click({
|
|
if ($script:UpdatingPresets) { return }
|
|
$check = ConvertTo-NormalizedCheckboxState -CheckBox $this
|
|
Invoke-AppPreset -AppsPanel $appsPanel -MatchFilter { param($c) $c.SelectedByDefault -eq $true } -Check $check
|
|
})
|
|
|
|
# ---- Clear selection button ----
|
|
$clearAppSelectionBtn.Add_Click({
|
|
Invoke-AppPreset -AppsPanel $appsPanel -MatchFilter { param($c) $true } -Check $false
|
|
})
|
|
|
|
# ---- Column header sort handlers ----
|
|
$headerNameBtn.Add_MouseLeftButtonUp({ & $setSortColumn 'Name' })
|
|
$headerDescriptionBtn.Add_MouseLeftButtonUp({ & $setSortColumn 'Description' })
|
|
$headerAppIdBtn.Add_MouseLeftButtonUp({ & $setSortColumn 'AppId' })
|
|
|
|
# ---- Load apps ----
|
|
$appLoadStatusCallback = { Update-AppSelectionStatus -AppsPanel $appsPanel -AppSelectionStatus $appSelectionStatus -AppRemovalScopeCombo $appRemovalScopeCombo -AppRemovalScopeSection $appRemovalScopeSection -AppRemovalScopeDescription $appRemovalScopeDescription -UserSelectionCombo $userSelectionCombo }
|
|
$onlyInstalledAppsBox.Add_Checked({ Load-AppsIntoMainUI -Window $window -AppsPanel $appsPanel -OnlyInstalledAppsBox $onlyInstalledAppsBox -LoadingAppsIndicator $loadingAppsIndicator -ImportConfigBtn $importConfigBtn })
|
|
$onlyInstalledAppsBox.Add_Unchecked({ Load-AppsIntoMainUI -Window $window -AppsPanel $appsPanel -OnlyInstalledAppsBox $onlyInstalledAppsBox -LoadingAppsIndicator $loadingAppsIndicator -ImportConfigBtn $importConfigBtn })
|
|
|
|
# ---- App presets popup ----
|
|
$presetsPopup.Add_Opened({
|
|
Update-AppPresetStates -AppsPanel $appsPanel
|
|
Start-DropdownArrowAnimation -Arrow $presetsArrow -Angle 180
|
|
})
|
|
$presetsPopup.Add_Closed({
|
|
Start-DropdownArrowAnimation -Arrow $presetsArrow -Angle 0
|
|
$presetsBtn.IsChecked = $false
|
|
})
|
|
|
|
$tweaksPresetsPopup.Add_Opened({
|
|
Update-TweakPresetStates -Window $window
|
|
Start-DropdownArrowAnimation -Arrow $tweaksPresetsArrow -Angle 180
|
|
})
|
|
$tweaksPresetsPopup.Add_Closed({
|
|
Start-DropdownArrowAnimation -Arrow $tweaksPresetsArrow -Angle 0
|
|
$tweaksPresetsBtn.IsChecked = $false
|
|
})
|
|
|
|
# ---- Popup dismiss on outside click ----
|
|
$window.Add_PreviewMouseDown({
|
|
$isAppPopupOpen = $presetsPopup.IsOpen
|
|
$isTweaksPopupOpen = $tweaksPresetsPopup.IsOpen
|
|
if (-not $isAppPopupOpen -and -not $isTweaksPopupOpen) { return }
|
|
|
|
if ($isAppPopupOpen -and $null -ne $presetsPopup.Child -and $presetsPopup.Child.IsMouseOver) { return }
|
|
if ($isTweaksPopupOpen -and $null -ne $tweaksPresetsPopup.Child -and $tweaksPresetsPopup.Child.IsMouseOver) { return }
|
|
|
|
$src = $_.OriginalSource -as [System.Windows.DependencyObject]
|
|
if ($null -ne $src) {
|
|
$inAppBtn = $presetsBtn.IsAncestorOf($src) -or [System.Object]::ReferenceEquals($presetsBtn, $src)
|
|
$inTweaksBtn = $tweaksPresetsBtn.IsAncestorOf($src) -or [System.Object]::ReferenceEquals($tweaksPresetsBtn, $src)
|
|
|
|
if ($isAppPopupOpen -and -not $inAppBtn) { $presetsPopup.IsOpen = $false }
|
|
if ($isTweaksPopupOpen -and -not $inTweaksBtn) { $tweaksPresetsPopup.IsOpen = $false }
|
|
}
|
|
})
|
|
|
|
$window.Add_Deactivated({
|
|
if ($presetsPopup.IsOpen) { $presetsPopup.IsOpen = $false }
|
|
if ($tweaksPresetsPopup.IsOpen) { $tweaksPresetsPopup.IsOpen = $false }
|
|
})
|
|
|
|
# ---- Toggle popup on button click ----
|
|
$presetsBtn.Add_Click({
|
|
$presetsPopup.IsOpen = -not $presetsPopup.IsOpen
|
|
$presetsBtn.IsChecked = $presetsPopup.IsOpen
|
|
})
|
|
|
|
$tweaksPresetsBtn.Add_Click({
|
|
$tweaksPresetsPopup.IsOpen = -not $tweaksPresetsPopup.IsOpen
|
|
$tweaksPresetsBtn.IsChecked = $tweaksPresetsPopup.IsOpen
|
|
})
|
|
|
|
# ---- App Search Box ----
|
|
$appSearchBox = $window.FindName('AppSearchBox')
|
|
$appSearchPlaceholder = $window.FindName('AppSearchPlaceholder')
|
|
|
|
$appSearchBox.Add_TextChanged({
|
|
$searchText = $appSearchBox.Text.ToLower().Trim()
|
|
$appSearchPlaceholder.Visibility = if ([string]::IsNullOrWhiteSpace($appSearchBox.Text)) { 'Visible' } else { 'Collapsed' }
|
|
|
|
foreach ($child in $appsPanel.Children) {
|
|
if ($child -is [System.Windows.Controls.CheckBox]) {
|
|
$child.Background = [System.Windows.Media.Brushes]::Transparent
|
|
}
|
|
}
|
|
|
|
$script:AppSearchMatches = @()
|
|
$script:AppSearchMatchIndex = -1
|
|
|
|
if ([string]::IsNullOrWhiteSpace($searchText)) { return }
|
|
|
|
$highlightBrush = $window.Resources["SearchHighlightColor"]
|
|
$activeHighlightBrush = $window.Resources["SearchHighlightActiveColor"]
|
|
|
|
foreach ($child in $appsPanel.Children) {
|
|
if ($child -is [System.Windows.Controls.CheckBox] -and $child.Visibility -eq 'Visible') {
|
|
$appName = if ($child.AppName) { $child.AppName } else { '' }
|
|
$appId = if ($child.Tag) { $child.Tag.ToString() } else { '' }
|
|
$appDesc = if ($child.AppDescription) { $child.AppDescription } else { '' }
|
|
if ($appName.ToLower().Contains($searchText) -or $appId.ToLower().Contains($searchText) -or $appDesc.ToLower().Contains($searchText)) {
|
|
$child.Background = $highlightBrush
|
|
$script:AppSearchMatches += $child
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($script:AppSearchMatches.Count -gt 0) {
|
|
$script:AppSearchMatchIndex = 0
|
|
$script:AppSearchMatches[0].Background = $activeHighlightBrush
|
|
$scrollViewer = Find-ParentScrollViewer -Element $appsPanel
|
|
if ($scrollViewer) {
|
|
Scroll-ToItemIfNotVisible -ScrollViewer $scrollViewer -Item $script:AppSearchMatches[0] -Container $appsPanel
|
|
}
|
|
}
|
|
})
|
|
|
|
$appSearchBox.Add_KeyDown({
|
|
param($sourceControl, $e)
|
|
if ($e.Key -eq [System.Windows.Input.Key]::Enter -and $script:AppSearchMatches.Count -gt 0) {
|
|
$script:AppSearchMatches[$script:AppSearchMatchIndex].Background = $window.Resources["SearchHighlightColor"]
|
|
$script:AppSearchMatchIndex = ($script:AppSearchMatchIndex + 1) % $script:AppSearchMatches.Count
|
|
$script:AppSearchMatches[$script:AppSearchMatchIndex].Background = $window.Resources["SearchHighlightActiveColor"]
|
|
$scrollViewer = Find-ParentScrollViewer -Element $appsPanel
|
|
if ($scrollViewer) {
|
|
Scroll-ToItemIfNotVisible -ScrollViewer $scrollViewer -Item $script:AppSearchMatches[$script:AppSearchMatchIndex] -Container $appsPanel
|
|
}
|
|
$e.Handled = $true
|
|
}
|
|
})
|
|
|
|
# ---- Tweak Search Box ----
|
|
$tweaksScrollViewer.Add_ScrollChanged({
|
|
if ($tweaksScrollViewer.ScrollableHeight -gt 0) {
|
|
$tweakSearchBorder.Margin = [System.Windows.Thickness]::new(0, 0, 17, 0)
|
|
}
|
|
else {
|
|
$tweakSearchBorder.Margin = [System.Windows.Thickness]::new(0)
|
|
}
|
|
})
|
|
|
|
$tweakSearchBox.Add_TextChanged({
|
|
$searchText = $tweakSearchBox.Text.ToLower().Trim()
|
|
$tweakSearchPlaceholder.Visibility = if ([string]::IsNullOrWhiteSpace($tweakSearchBox.Text)) { 'Visible' } else { 'Collapsed' }
|
|
|
|
Clear-TweakHighlights -Window $window
|
|
|
|
if ([string]::IsNullOrWhiteSpace($searchText)) { return }
|
|
|
|
$firstMatch = $null
|
|
$highlightBrush = $window.Resources["SearchHighlightColor"]
|
|
$col0 = $window.FindName('Column0Panel')
|
|
$col1 = $window.FindName('Column1Panel')
|
|
$col2 = $window.FindName('Column2Panel')
|
|
$columns = @($col0, $col1, $col2) | Where-Object { $_ -ne $null }
|
|
|
|
foreach ($column in $columns) {
|
|
foreach ($card in $column.Children) {
|
|
if ($card -is [System.Windows.Controls.Border] -and $card.Child -is [System.Windows.Controls.StackPanel]) {
|
|
$controlsList = @($card.Child.Children)
|
|
for ($i = 0; $i -lt $controlsList.Count; $i++) {
|
|
$control = $controlsList[$i]
|
|
$matchFound = $false
|
|
$controlToHighlight = $null
|
|
|
|
if ($control -is [System.Windows.Controls.CheckBox]) {
|
|
if ($control.Content.ToString().ToLower().Contains($searchText)) {
|
|
$matchFound = $true
|
|
$controlToHighlight = $control
|
|
}
|
|
}
|
|
elseif ($control -is [System.Windows.Controls.Border] -and $control.Name -like '*_LabelBorder') {
|
|
$labelText = if ($control.Child) { $control.Child.Text.ToLower() } else { "" }
|
|
$comboBox = if ($i + 1 -lt $controlsList.Count -and $controlsList[$i + 1] -is [System.Windows.Controls.ComboBox]) { $controlsList[$i + 1] } else { $null }
|
|
|
|
if ($labelText.Contains($searchText) -or ($comboBox -and (Test-ComboBoxContainsMatch -ComboBox $comboBox -SearchText $searchText))) {
|
|
$matchFound = $true
|
|
$controlToHighlight = $control
|
|
}
|
|
}
|
|
|
|
if ($matchFound -and $controlToHighlight) {
|
|
$controlToHighlight.Background = $highlightBrush
|
|
if ($null -eq $firstMatch) { $firstMatch = $controlToHighlight }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($firstMatch -and $tweaksScrollViewer) {
|
|
Scroll-ToItemIfNotVisible -ScrollViewer $tweaksScrollViewer -Item $firstMatch -Container $tweaksGrid
|
|
}
|
|
})
|
|
|
|
# ---- Show currently applied tweaks checkbox ----
|
|
if ($ShowCurrentlyAppliedTweaksCheckBox) {
|
|
$ShowCurrentlyAppliedTweaksCheckBox.Add_Checked({
|
|
Reset-TweaksToSystemState -Window $window -LoadSystemState $true
|
|
Update-AppliedTweaksUserModeState -ShowCurrentlyAppliedTweaksCheckBox $ShowCurrentlyAppliedTweaksCheckBox -UserSelectionCombo $userSelectionCombo
|
|
})
|
|
$ShowCurrentlyAppliedTweaksCheckBox.Add_Unchecked({
|
|
Reset-TweaksToSystemState -Window $window -LoadSystemState $false
|
|
Update-AppliedTweaksUserModeState -ShowCurrentlyAppliedTweaksCheckBox $ShowCurrentlyAppliedTweaksCheckBox -UserSelectionCombo $userSelectionCombo
|
|
})
|
|
}
|
|
|
|
# ---- Ctrl+F keyboard shortcut ----
|
|
$window.Add_KeyDown({
|
|
param($sourceControl, $e)
|
|
if ($e.Key -eq [System.Windows.Input.Key]::F -and
|
|
([System.Windows.Input.Keyboard]::Modifiers -band [System.Windows.Input.ModifierKeys]::Control)) {
|
|
$currentTab = $tabControl.SelectedItem
|
|
if ($currentTab.Header -eq "App Removal" -and $appSearchBox) {
|
|
$appSearchBox.Focus()
|
|
$e.Handled = $true
|
|
}
|
|
elseif ($currentTab.Header -eq "Tweaks" -and $tweakSearchBox) {
|
|
$tweakSearchBox.Focus()
|
|
$e.Handled = $true
|
|
}
|
|
}
|
|
})
|
|
|
|
# ---- Navigation button handlers ----
|
|
function Invoke-NavigationUpdate {
|
|
Update-NavigationButtons -Window $window -TabControl $tabControl
|
|
}
|
|
|
|
$previousBtn.Add_Click({
|
|
Hide-Bubble -Immediate
|
|
if ($tabControl.SelectedIndex -gt 0) {
|
|
$tabControl.SelectedIndex--
|
|
Invoke-NavigationUpdate
|
|
}
|
|
})
|
|
|
|
$nextBtn.Add_Click({
|
|
if ($tabControl.SelectedIndex -lt ($tabControl.Items.Count - 1)) {
|
|
$tabControl.SelectedIndex++
|
|
Invoke-NavigationUpdate
|
|
}
|
|
})
|
|
|
|
# ---- User selection combo ----
|
|
$userSelectionCombo.Add_SelectionChanged({
|
|
Update-UserSelectionDescription -Window $window -UserSelectionCombo $userSelectionCombo -OtherUsernameTextBox $otherUsernameTextBox -UserSelectionDescription $userSelectionDescription
|
|
|
|
switch ($userSelectionCombo.SelectedIndex) {
|
|
0 {
|
|
$otherUserPanel.Visibility = 'Collapsed'
|
|
$usernameValidationMessage.Text = ""
|
|
$appRemovalScopeCurrentUser.Visibility = 'Visible'
|
|
$appRemovalScopeTargetUser.Visibility = 'Collapsed'
|
|
$appRemovalScopeCombo.SelectedIndex = 0
|
|
if ($ShowCurrentlyAppliedTweaksCheckBox -and $ShowCurrentlyAppliedTweaksCheckBox.IsChecked -ne $true) {
|
|
$ShowCurrentlyAppliedTweaksCheckBox.IsChecked = $true
|
|
}
|
|
}
|
|
1 {
|
|
$otherUserPanel.Visibility = 'Visible'
|
|
$usernameValidationMessage.Text = ""
|
|
$appRemovalScopeCurrentUser.Visibility = 'Collapsed'
|
|
$appRemovalScopeTargetUser.Visibility = 'Visible'
|
|
$appRemovalScopeCombo.SelectedIndex = 0
|
|
if ($ShowCurrentlyAppliedTweaksCheckBox -and $ShowCurrentlyAppliedTweaksCheckBox.IsChecked -eq $true) {
|
|
$ShowCurrentlyAppliedTweaksCheckBox.IsChecked = $false
|
|
}
|
|
}
|
|
2 {
|
|
$otherUserPanel.Visibility = 'Collapsed'
|
|
$usernameValidationMessage.Text = ""
|
|
$appRemovalScopeCurrentUser.Visibility = 'Collapsed'
|
|
$appRemovalScopeTargetUser.Visibility = 'Collapsed'
|
|
$appRemovalScopeCombo.SelectedIndex = 0
|
|
if ($ShowCurrentlyAppliedTweaksCheckBox -and $ShowCurrentlyAppliedTweaksCheckBox.IsChecked -eq $true) {
|
|
$ShowCurrentlyAppliedTweaksCheckBox.IsChecked = $false
|
|
}
|
|
}
|
|
}
|
|
|
|
Update-AppSelectionStatus -AppsPanel $appsPanel -AppSelectionStatus $appSelectionStatus -AppRemovalScopeCombo $appRemovalScopeCombo -AppRemovalScopeSection $appRemovalScopeSection -AppRemovalScopeDescription $appRemovalScopeDescription -UserSelectionCombo $userSelectionCombo
|
|
Update-AppliedTweaksUserModeState -ShowCurrentlyAppliedTweaksCheckBox $ShowCurrentlyAppliedTweaksCheckBox -UserSelectionCombo $userSelectionCombo
|
|
})
|
|
|
|
# ---- App removal scope combo ----
|
|
$appRemovalScopeCombo.Add_SelectionChanged({
|
|
Update-AppRemovalScopeDescription -AppRemovalScopeCombo $appRemovalScopeCombo -AppRemovalScopeDescription $appRemovalScopeDescription
|
|
})
|
|
|
|
# ---- Other username text box ----
|
|
$otherUsernameTextBox.Add_TextChanged({
|
|
if ([string]::IsNullOrWhiteSpace($otherUsernameTextBox.Text)) {
|
|
$usernameTextBoxPlaceholder.Visibility = 'Visible'
|
|
}
|
|
else {
|
|
$usernameTextBoxPlaceholder.Visibility = 'Collapsed'
|
|
}
|
|
Update-UserSelectionDescription -Window $window -UserSelectionCombo $userSelectionCombo -OtherUsernameTextBox $otherUsernameTextBox -UserSelectionDescription $userSelectionDescription
|
|
Test-OtherUsername -Window $window -UserSelectionCombo $userSelectionCombo -OtherUsernameTextBox $otherUsernameTextBox -UsernameValidationMessage $usernameValidationMessage | Out-Null
|
|
})
|
|
|
|
# ---- Validate target user helper ----
|
|
$ensureValidTargetUserOrWarn = {
|
|
if (-not (Test-OtherUsername -Window $window -UserSelectionCombo $userSelectionCombo -OtherUsernameTextBox $otherUsernameTextBox -UsernameValidationMessage $usernameValidationMessage)) {
|
|
$validationMessage = if (-not [string]::IsNullOrWhiteSpace($usernameValidationMessage.Text)) {
|
|
$usernameValidationMessage.Text
|
|
}
|
|
else {
|
|
"Please enter a valid username."
|
|
}
|
|
Show-MessageBox -Message $validationMessage -Title "Invalid Username" -Button 'OK' -Icon 'Warning' | Out-Null
|
|
return $false
|
|
}
|
|
return $true
|
|
}
|
|
|
|
# ---- Home Start button ----
|
|
$homeStartBtn.Add_Click({
|
|
if (-not (& $ensureValidTargetUserOrWarn)) { return }
|
|
$tabControl.SelectedIndex = 1
|
|
Invoke-NavigationUpdate
|
|
})
|
|
|
|
# ---- Home Default Mode button ----
|
|
$homeDefaultModeBtn.Add_Click({
|
|
if (-not (& $ensureValidTargetUserOrWarn)) { return }
|
|
|
|
if ($ShowCurrentlyAppliedTweaksCheckBox) {
|
|
$ShowCurrentlyAppliedTweaksCheckBox.IsChecked = $false
|
|
}
|
|
|
|
$defaultsJson = LoadJsonFile -filePath $script:DefaultSettingsFilePath -expectedVersion "1.0"
|
|
if ($defaultsJson) {
|
|
ApplySettingsToUiControls -window $window -settingsJson $defaultsJson -uiControlMappings $script:UiControlMappings
|
|
}
|
|
|
|
if ($script:IsLoadingApps) {
|
|
$script:PendingDefaultMode = $true
|
|
}
|
|
else {
|
|
Invoke-AppPreset -AppsPanel $appsPanel -MatchFilter { param($c) $c.SelectedByDefault -eq $true } -Exclusive
|
|
}
|
|
|
|
$tabControl.SelectedIndex = 3
|
|
Invoke-NavigationUpdate
|
|
|
|
$window.Dispatcher.BeginInvoke([System.Windows.Threading.DispatcherPriority]::Loaded, [action]{
|
|
Show-Bubble -TargetControl $reviewChangesBtn -Message 'View the selected changes here'
|
|
}) | Out-Null
|
|
})
|
|
|
|
# ---- Review Changes link ----
|
|
$reviewChangesBtn.Add_Click({
|
|
Hide-Bubble
|
|
Invoke-ShowChangesOverview -Window $window -AppsPanel $appsPanel -ShowCurrentlyAppliedTweaksCheckBox $ShowCurrentlyAppliedTweaksCheckBox
|
|
})
|
|
|
|
# ---- Apply Changes button ----
|
|
$deploymentApplyBtn.Add_Click({
|
|
if (-not (& $ensureValidTargetUserOrWarn)) { return }
|
|
|
|
Hide-Bubble -Immediate
|
|
|
|
$showAppliedTweaksMode = ($ShowCurrentlyAppliedTweaksCheckBox -and $ShowCurrentlyAppliedTweaksCheckBox.IsChecked -eq $true)
|
|
$selectedForwardFeatureIds = New-Object 'System.Collections.Generic.HashSet[string]' ([System.StringComparer]::OrdinalIgnoreCase)
|
|
|
|
# App Removal - collect selected apps
|
|
$selectedApps = @()
|
|
foreach ($child in $appsPanel.Children) {
|
|
if ($child -is [System.Windows.Controls.CheckBox] -and $child.IsChecked) {
|
|
$selectedApps += @($child.AppIds)
|
|
}
|
|
}
|
|
$selectedApps = @($selectedApps | Where-Object { $_ } | Select-Object -Unique)
|
|
$hasAppSelection = ($selectedApps.Count -gt 0)
|
|
|
|
if ($selectedApps.Count -gt 0) {
|
|
if (-not (ConfirmUnsafeAppRemoval -SelectedApps $selectedApps -Owner $window)) { return }
|
|
|
|
AddParameter 'RemoveApps'
|
|
AddParameter 'Apps' ($selectedApps -join ',')
|
|
|
|
$selectedScopeItem = $appRemovalScopeCombo.SelectedItem
|
|
if ($selectedScopeItem) {
|
|
switch ($selectedScopeItem.Content) {
|
|
"All users" { AddParameter 'AppRemovalTarget' 'AllUsers' }
|
|
"Current user only" { AddParameter 'AppRemovalTarget' 'CurrentUser' }
|
|
"Target user only" { AddParameter 'AppRemovalTarget' ($otherUsernameTextBox.Text.Trim()) }
|
|
}
|
|
}
|
|
}
|
|
|
|
# Apply dynamic tweaks
|
|
foreach ($tweakAction in @(Get-PendingTweakActions -Window $window -ShowAppliedTweaksMode:$showAppliedTweaksMode)) {
|
|
if ($tweakAction.Action -eq 'Apply') {
|
|
AddParameter $tweakAction.FeatureId
|
|
$null = $selectedForwardFeatureIds.Add([string]$tweakAction.FeatureId)
|
|
continue
|
|
}
|
|
$script:UndoParams[[string]$tweakAction.FeatureId] = $true
|
|
}
|
|
|
|
if (-not $hasAppSelection -and $selectedForwardFeatureIds.Count -eq 0 -and $script:UndoParams.Count -eq 0) {
|
|
Show-MessageBox -Message 'No changes have been selected, please select at least one option to proceed.' -Title 'No Changes Selected' -Button 'OK' -Icon 'Information'
|
|
return
|
|
}
|
|
|
|
$restorePointCheckBox = $window.FindName('RestorePointCheckBox')
|
|
if ($restorePointCheckBox -and $restorePointCheckBox.IsChecked) {
|
|
AddParameter 'CreateRestorePoint'
|
|
}
|
|
|
|
switch ($userSelectionCombo.SelectedIndex) {
|
|
0 { Write-Host "Selected user mode: current user ($(GetUserName))" }
|
|
1 {
|
|
Write-Host "Selected user mode: $($otherUsernameTextBox.Text.Trim())"
|
|
AddParameter User ($otherUsernameTextBox.Text.Trim())
|
|
}
|
|
2 {
|
|
Write-Host "Selected user mode: default user profile (Sysprep)"
|
|
AddParameter Sysprep
|
|
}
|
|
}
|
|
|
|
SaveSettings
|
|
|
|
$restartExplorerCheckBox = $window.FindName('RestartExplorerCheckBox')
|
|
$shouldRestartExplorer = $restartExplorerCheckBox -and $restartExplorerCheckBox.IsChecked
|
|
|
|
Show-ApplyModal -Owner $window -RestartExplorer $shouldRestartExplorer
|
|
$window.Close()
|
|
})
|
|
|
|
# ---- Tweaks presets tri-state ----
|
|
foreach ($presetCheckBox in @($presetDefaultTweaksBtn, $presetLastUsedTweaksBtn, $presetPrivacyTweaksBtn, $presetAITweaksBtn)) {
|
|
Add-TriStateClickBehavior -CheckBox $presetCheckBox
|
|
}
|
|
|
|
# ---- Clear All Tweaks ----
|
|
$clearAllTweaksBtn.Add_Click({
|
|
if ($ShowCurrentlyAppliedTweaksCheckBox -and $ShowCurrentlyAppliedTweaksCheckBox.IsChecked -eq $true) {
|
|
$ShowCurrentlyAppliedTweaksCheckBox.IsChecked = $false
|
|
}
|
|
Clear-TweakSelections -Window $window
|
|
Update-TweakPresetStates -Window $window
|
|
})
|
|
|
|
# ---- Window Load event ----
|
|
$window.Add_Loaded({
|
|
try {
|
|
& $updateHomeContentPosition
|
|
Build-DynamicTweaks -Window $window -WinVersion $WinVersion
|
|
Load-CurrentTweakStateIntoUI -Window $window
|
|
Update-TweaksResponsiveColumns -Window $window
|
|
|
|
$lastUsedSettingsJson = LoadJsonFile -filePath $script:SavedSettingsFilePath -expectedVersion "1.0" -optionalFile
|
|
$defaultsJson = LoadJsonFile -filePath $script:DefaultSettingsFilePath -expectedVersion "1.0"
|
|
|
|
$script:SavedAppIds = Get-SavedAppIdsFromSettingsJson -SettingsJson $lastUsedSettingsJson
|
|
|
|
Initialize-TweakPresetSources -Window $window -DefaultSettingsJson $defaultsJson -LastUsedSettingsJson $lastUsedSettingsJson
|
|
Register-TweakPresetControlStateHandlers -Window $window
|
|
Update-TweakPresetStates -Window $window
|
|
|
|
Load-AppsIntoMainUI -Window $window -AppsPanel $appsPanel -OnlyInstalledAppsBox $onlyInstalledAppsBox -LoadingAppsIndicator $loadingAppsIndicator -ImportConfigBtn $importConfigBtn
|
|
|
|
# Update Current User label
|
|
if ($userSelectionCombo -and $userSelectionCombo.Items.Count -gt 0) {
|
|
$currentUserItem = $userSelectionCombo.Items[0]
|
|
if ($currentUserItem -is [System.Windows.Controls.ComboBoxItem]) {
|
|
$currentUserItem.Content = "Current User ($(GetUserName))"
|
|
}
|
|
}
|
|
|
|
$restartExplorerCheckBox = $window.FindName('RestartExplorerCheckBox')
|
|
if ($restartExplorerCheckBox -and $script:Params.ContainsKey("NoRestartExplorer")) {
|
|
$restartExplorerCheckBox.IsChecked = $false
|
|
$restartExplorerCheckBox.IsEnabled = $false
|
|
}
|
|
|
|
if ($script:Params.ContainsKey("Sysprep")) {
|
|
$userSelectionCombo.SelectedIndex = 2
|
|
$userSelectionCombo.IsEnabled = $false
|
|
}
|
|
elseif ($script:Params.ContainsKey("User")) {
|
|
$userSelectionCombo.SelectedIndex = 1
|
|
$userSelectionCombo.IsEnabled = $false
|
|
$otherUsernameTextBox.Text = $script:Params.Item("User")
|
|
$otherUsernameTextBox.IsEnabled = $false
|
|
}
|
|
|
|
Update-UserSelectionDescription -Window $window -UserSelectionCombo $userSelectionCombo -OtherUsernameTextBox $otherUsernameTextBox -UserSelectionDescription $userSelectionDescription
|
|
Update-AppliedTweaksUserModeState -ShowCurrentlyAppliedTweaksCheckBox $ShowCurrentlyAppliedTweaksCheckBox -UserSelectionCombo $userSelectionCombo
|
|
Invoke-NavigationUpdate
|
|
}
|
|
catch {
|
|
Write-Warning "Error during GUI initialization: $($_.Exception.Message)"
|
|
Write-Warning "Stack trace: $($_.Exception.StackTrace)"
|
|
Show-MessageBox -Message "An error occurred during initialization: $($_.Exception.Message)" -Title "Initialization Error" -Button 'OK' -Icon 'Error' | Out-Null
|
|
}
|
|
})
|
|
|
|
# ---- Tab change event ----
|
|
$tabControl.Add_SelectionChanged({
|
|
if ($tabControl.SelectedIndex -eq ($tabControl.Items.Count - 2)) {
|
|
New-Overview -Window $window -AppsPanel $appsPanel -ShowCurrentlyAppliedTweaksCheckBox $ShowCurrentlyAppliedTweaksCheckBox | Out-Null
|
|
}
|
|
Invoke-NavigationUpdate
|
|
})
|
|
|
|
# ---- Tweak presets wiring ----
|
|
$lastUsedSettingsJson = LoadJsonFile -filePath $script:SavedSettingsFilePath -expectedVersion "1.0" -optionalFile
|
|
$defaultsJson = LoadJsonFile -filePath $script:DefaultSettingsFilePath -expectedVersion "1.0"
|
|
$script:DefaultTweakPresetMap = @{}
|
|
$script:LastUsedTweakPresetMap = @{}
|
|
$script:PrivacyTweakPresetMap = @{}
|
|
$script:AITweakPresetMap = @{}
|
|
$script:SavedAppIds = Get-SavedAppIdsFromSettingsJson -SettingsJson $lastUsedSettingsJson
|
|
|
|
if ($presetDefaultTweaksBtn) {
|
|
$presetDefaultTweaksBtn.Add_Click({
|
|
if ($script:UpdatingTweakPresets) { return }
|
|
$check = ConvertTo-NormalizedCheckboxState -CheckBox $this
|
|
Invoke-ApplyTweakPresetMap -PresetMap $script:DefaultTweakPresetMap -Check $check
|
|
})
|
|
}
|
|
|
|
if ($presetLastUsedTweaksBtn) {
|
|
$presetLastUsedTweaksBtn.Add_Click({
|
|
if ($script:UpdatingTweakPresets) { return }
|
|
$check = ConvertTo-NormalizedCheckboxState -CheckBox $this
|
|
Invoke-ApplyTweakPresetMap -PresetMap $script:LastUsedTweakPresetMap -Check $check
|
|
})
|
|
}
|
|
|
|
if ($presetPrivacyTweaksBtn) {
|
|
$presetPrivacyTweaksBtn.Add_Click({
|
|
if ($script:UpdatingTweakPresets) { return }
|
|
$check = ConvertTo-NormalizedCheckboxState -CheckBox $this
|
|
Invoke-ApplyTweakPresetMap -PresetMap $script:PrivacyTweakPresetMap -Check $check
|
|
})
|
|
}
|
|
|
|
if ($presetAITweaksBtn) {
|
|
$presetAITweaksBtn.Add_Click({
|
|
if ($script:UpdatingTweakPresets) { return }
|
|
$check = ConvertTo-NormalizedCheckboxState -CheckBox $this
|
|
Invoke-ApplyTweakPresetMap -PresetMap $script:AITweakPresetMap -Check $check
|
|
})
|
|
}
|
|
|
|
# Hide Last used tweak preset by default
|
|
if ($presetLastUsedTweaksBtn) {
|
|
$presetLastUsedTweaksBtn.Visibility = 'Collapsed'
|
|
}
|
|
|
|
# ---- Preset: Last used selection (apps) ----
|
|
if ($script:SavedAppIds) {
|
|
$presetLastUsed.Add_Click({
|
|
if ($script:UpdatingPresets) { return }
|
|
$check = ConvertTo-NormalizedCheckboxState -CheckBox $this
|
|
Invoke-AppPreset -AppsPanel $appsPanel -MatchFilter { param($c) (@($c.AppIds) | Where-Object { $script:SavedAppIds -contains $_ }).Count -gt 0 } -Check $check
|
|
})
|
|
}
|
|
else {
|
|
$script:SavedAppIds = $null
|
|
$presetLastUsed.Visibility = 'Collapsed'
|
|
}
|
|
|
|
# ---- Preload app data ----
|
|
try {
|
|
$script:PreloadedAppData = LoadAppsDetailsFromJson -OnlyInstalled:$false -InstalledList '' -InitialCheckedFromJson:$false
|
|
}
|
|
catch {
|
|
Write-Warning "Failed to preload apps list: $_"
|
|
}
|
|
|
|
# ---- Show window ----
|
|
$frame = [System.Windows.Threading.DispatcherFrame]::new()
|
|
$window.Add_Closed({
|
|
$frame.Continue = $false
|
|
})
|
|
|
|
$window.Show() | Out-Null
|
|
[System.Windows.Threading.Dispatcher]::PushFrame($frame)
|
|
return $null
|
|
}
|