From 12607cca449c47273abb201fad36397555c19a7c Mon Sep 17 00:00:00 2001 From: rbalsleyMSFT <53497092+rbalsleyMSFT@users.noreply.github.com> Date: Thu, 19 Jun 2025 12:23:13 -0700 Subject: [PATCH] Refactor: Move Winget download logic to core module Extracts the Winget app download logic from the main UI script into a new `Invoke-WingetDownload` function within the core Winget module. This change decouples the UI event handling from the business logic, improving modularity and maintainability. It also introduces more robust error handling for the download process by wrapping the logic in a try/catch block. --- FFUDevelopment/BuildFFUVM_UI.ps1 | 49 -------------- .../FFUUI.Core/FFUUI.Core.Handlers.psm1 | 7 ++ .../FFUUI.Core/FFUUI.Core.Winget.psm1 | 65 +++++++++++++++++-- 3 files changed, 68 insertions(+), 53 deletions(-) diff --git a/FFUDevelopment/BuildFFUVM_UI.ps1 b/FFUDevelopment/BuildFFUVM_UI.ps1 index c69f23e..84d3b72 100644 --- a/FFUDevelopment/BuildFFUVM_UI.ps1 +++ b/FFUDevelopment/BuildFFUVM_UI.ps1 @@ -187,55 +187,6 @@ $window.Add_Loaded({ $script:uiState.Controls.wingetPanel.Visibility = if ($script:uiState.Controls.chkInstallWingetApps.IsChecked) { 'Visible' } else { 'Collapsed' } $script:uiState.Controls.wingetSearchPanel.Visibility = 'Collapsed' # Keep search hidden initially - $script:uiState.Controls.btnDownloadSelected.Add_Click({ - param($buttonSender, $clickEventArgs) - - $selectedApps = $script:uiState.Controls.lstWingetResults.Items | Where-Object { $_.IsSelected } - if (-not $selectedApps) { - [System.Windows.MessageBox]::Show("No applications selected to download.", "Download Winget Apps", "OK", "Information") - return - } - - $buttonSender.IsEnabled = $false - $script:uiState.Controls.pbOverallProgress.Visibility = 'Visible' - $script:uiState.Controls.pbOverallProgress.Value = 0 - $script:uiState.Controls.txtStatus.Text = "Starting Winget app downloads..." - - # Define necessary task-specific variables locally - $localAppsPath = $script:uiState.Controls.txtApplicationPath.Text - $localAppListJsonPath = $script:uiState.Controls.txtAppListJsonPath.Text - $localWindowsArch = $script:uiState.Controls.cmbWindowsArch.SelectedItem - $localOrchestrationPath = Join-Path -Path $script:uiState.Controls.txtApplicationPath.Text -ChildPath "Orchestration" - - # Create hashtable for task-specific arguments to pass to Invoke-ParallelProcessing - $taskArguments = @{ - AppsPath = $localAppsPath - AppListJsonPath = $localAppListJsonPath - WindowsArch = $localWindowsArch - OrchestrationPath = $localOrchestrationPath - } - - # Select only necessary properties before passing to Invoke-ParallelProcessing - $itemsToProcess = $selectedApps | Select-Object Name, Id, Source, Version # Include Version if needed - - # Invoke the centralized parallel processing function - # Pass task type and task-specific arguments - Invoke-ParallelProcessing -ItemsToProcess $itemsToProcess ` - -ListViewControl $script:uiState.Controls.lstWingetResults ` - -IdentifierProperty 'Id' ` - -StatusProperty 'DownloadStatus' ` - -TaskType 'WingetDownload' ` - -TaskArguments $taskArguments ` - -CompletedStatusText "Completed" ` - -ErrorStatusPrefix "Error: " ` - -WindowObject $window ` - -MainThreadLogPath $script:uiState.LogFilePath - - # Final status update (handled by Invoke-ParallelProcessing) - $script:uiState.Controls.pbOverallProgress.Visibility = 'Collapsed' - $buttonSender.IsEnabled = $true - }) - # BYO Apps UI logic (Keep existing logic) $script:uiState.Controls.btnBrowseAppSource.Add_Click({ $selectedPath = Show-ModernFolderPicker -Title "Select Application Source Folder" diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Handlers.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Handlers.psm1 index d125ca9..d3d2b40 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Handlers.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Handlers.psm1 @@ -423,6 +423,13 @@ function Register-EventHandlers { -PostClearAction $postClearScriptBlock }) + $State.Controls.btnDownloadSelected.Add_Click({ + param($eventSource, $routedEventArgs) + $window = [System.Windows.Window]::GetWindow($eventSource) + $localState = $window.Tag + Invoke-WingetDownload -State $localState -Button $eventSource + }) + # M365 Apps/Office tab Event $State.Controls.chkInstallOffice.Add_Checked({ param($eventSource, $routedEventArgs) diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Winget.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Winget.psm1 index e447ade..57d8648 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Winget.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Winget.psm1 @@ -686,6 +686,67 @@ function Start-WingetAppDownloadTask { return $returnObject } +function Invoke-WingetDownload { + param( + [psobject]$State, + [object]$Button + ) + try { + $selectedApps = $State.Controls.lstWingetResults.Items | Where-Object { $_.IsSelected } + if (-not $selectedApps) { + [System.Windows.MessageBox]::Show("No applications selected to download.", "Download Winget Apps", "OK", "Information") + return + } + + $Button.IsEnabled = $false + $State.Controls.pbOverallProgress.Visibility = 'Visible' + $State.Controls.pbOverallProgress.Value = 0 + $State.Controls.txtStatus.Text = "Starting Winget app downloads..." + + # Define necessary task-specific variables locally + $localAppsPath = $State.Controls.txtApplicationPath.Text + $localAppListJsonPath = $State.Controls.txtAppListJsonPath.Text + $localWindowsArch = $State.Controls.cmbWindowsArch.SelectedItem + $localOrchestrationPath = Join-Path -Path $State.Controls.txtApplicationPath.Text -ChildPath "Orchestration" + + # Create hashtable for task-specific arguments to pass to Invoke-ParallelProcessing + $taskArguments = @{ + AppsPath = $localAppsPath + AppListJsonPath = $localAppListJsonPath + WindowsArch = $localWindowsArch + OrchestrationPath = $localOrchestrationPath + } + + # Select only necessary properties before passing to Invoke-ParallelProcessing + $itemsToProcess = $selectedApps | Select-Object Name, Id, Source, Version # Include Version if needed + + # Invoke the centralized parallel processing function + # Pass task type and task-specific arguments + Invoke-ParallelProcessing -ItemsToProcess $itemsToProcess ` + -ListViewControl $State.Controls.lstWingetResults ` + -IdentifierProperty 'Id' ` + -StatusProperty 'DownloadStatus' ` + -TaskType 'WingetDownload' ` + -TaskArguments $taskArguments ` + -CompletedStatusText "Completed" ` + -ErrorStatusPrefix "Error: " ` + -WindowObject $State.Window ` + -MainThreadLogPath $State.LogFilePath + + # Final status update is handled by Invoke-ParallelProcessing, but we need to re-enable the button + $State.Controls.pbOverallProgress.Visibility = 'Collapsed' + $Button.IsEnabled = $true + } + catch { + WriteLog "FATAL Error in Invoke-WingetDownload: $($_.Exception.ToString())" + [System.Windows.MessageBox]::Show("A critical error occurred while starting the Winget download: $($_.Exception.Message)", "Error", "OK", "Error") + # Reset UI state on error + if ($Button) { $Button.IsEnabled = $true } + if ($State.Controls.pbOverallProgress) { $State.Controls.pbOverallProgress.Visibility = 'Collapsed' } + if ($State.Controls.txtStatus) { $State.Controls.txtStatus.Text = "Winget download failed to start." } + } +} + function Update-WingetVersionFields { param( [psobject]$State, @@ -699,8 +760,4 @@ function Update-WingetVersionFields { }) } -# -------------------------------------------------------------------------- -# SECTION: Module Export -# -------------------------------------------------------------------------- - Export-ModuleMember -Function * \ No newline at end of file