Skip to content
Open
57 changes: 57 additions & 0 deletions functions/private/Close-WinUtilFaviconRunspacePool.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
function Close-WinUtilFaviconRunspacePool {
<#
.SYNOPSIS
Stops favicon work and disposes its timer, operations, circuit breaker, and runspace pool.
#>
if ($null -eq $sync) {
return
}

if ($sync.FaviconCircuitBreaker) {
$sync.FaviconCircuitBreaker.Cancel()
}

if ($sync.FaviconTimer) {
$sync.FaviconTimer.Stop()
$sync.Remove("FaviconTimer")
}

if ($sync.ContainsKey("FaviconQueue") -and $null -ne $sync.FaviconQueue) {
$sync.FaviconQueue.Clear()
$sync.Remove("FaviconQueue")
}

if ($sync.FaviconOperations) {
foreach ($operation in @($sync.FaviconOperations.Values)) {
try {
$operation.PowerShell.Stop()
} catch {
}
try {
$operation.PowerShell.Dispose()
} catch {
}
}
$sync.FaviconOperations.Clear()
}
Comment thread
mewclouds marked this conversation as resolved.

if ($sync.FaviconRunspace) {
try {
if ($sync.FaviconRunspace.RunspacePoolStateInfo.State -notin @(
[System.Management.Automation.Runspaces.RunspacePoolState]::Closed,
[System.Management.Automation.Runspaces.RunspacePoolState]::Closing,
[System.Management.Automation.Runspaces.RunspacePoolState]::Broken
)) {
$sync.FaviconRunspace.Close()
}
} finally {
$sync.FaviconRunspace.Dispose()
$sync.Remove("FaviconRunspace")
}
}

if ($sync.FaviconCircuitBreaker) {
$sync.FaviconCircuitBreaker.Dispose()
$sync.Remove("FaviconCircuitBreaker")
}
}
19 changes: 19 additions & 0 deletions functions/private/Get-WinUtilFaviconUrl.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
function Get-WinUtilFaviconUrl {
<#
.SYNOPSIS
Builds the Google favicon service URL for an application link.
.PARAMETER Link
The application website URL whose favicon should be requested.
#>
param(
[Parameter(Mandatory = $true)]
[string]$Link
)

if ([string]::IsNullOrWhiteSpace($Link)) {
return $null
}

$faviconSize = 64
return "https://www.google.com/s2/favicons?sz=$faviconSize&domain_url=$([uri]::EscapeDataString($Link))"
}
18 changes: 15 additions & 3 deletions functions/private/Initialize-InstallAppEntry.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,15 @@ function Initialize-InstallAppEntry {
$fallback = New-Object Windows.Controls.TextBlock
$fallback.Text = $app.content.TrimStart(".").Substring(0, 1).ToUpper()
$fallback.FontWeight = "Bold"; $fallback.HorizontalAlignment = "Center"; $fallback.VerticalAlignment = "Center"
if ($app.link) { $fallback.Visibility = "Collapsed" }
$fallback.SetResourceReference([Windows.Controls.TextBlock]::FontSizeProperty, "AppEntryFontSize")
$fallback.SetResourceReference([Windows.Controls.TextBlock]::ForegroundProperty, "ToggleButtonOnColor")
[void]$icon.Children.Add($fallback)
$faviconUrl = $null
if ($app.link) {
$logo = New-Object Windows.Controls.Image
$logo.Stretch = [Windows.Media.Stretch]::Uniform
$logo.Source = "https://www.google.com/s2/favicons?sz=64&domain_url=$([uri]::EscapeDataString($app.link))"
$logo.Add_ImageFailed({ $this.Visibility = "Collapsed"; $this.Parent.Children[0].Visibility = "Visible" })
$logo.Visibility = [Windows.Visibility]::Collapsed
$faviconUrl = Get-WinUtilFaviconUrl -Link $app.link
[void]$icon.Children.Add($logo)
}
[void]$contentPanel.Children.Add($icon)
Expand Down Expand Up @@ -116,5 +116,17 @@ function Initialize-InstallAppEntry {
}
# Add the border to the corresponding Category
$TargetElement.Children.Add($border) | Out-Null
if ($faviconUrl) {
if ($null -eq $sync.FaviconQueue) {
$sync.FaviconQueue = [System.Collections.Queue]::new()
}

$sync.FaviconQueue.Enqueue([pscustomobject]@{
AppKey = $appKey
Url = $faviconUrl
TargetImage = $logo
Fallback = $fallback
})
}
return $checkbox
}
1 change: 1 addition & 0 deletions functions/private/Initialize-InstallCategoryAppList.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ function Initialize-InstallCategoryAppList {
$appsByCategory[$category] += $appKey
}
$sync.InstallAppRenderQueue = [System.Collections.Queue]::new()
$sync.FaviconQueue = [System.Collections.Queue]::new()

foreach ($category in $($appsByCategory.Keys | Sort-Object)) {
# Create a container for category label + apps
Expand Down
40 changes: 40 additions & 0 deletions functions/private/Initialize-WinUtilFaviconRunspacePool.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
function Initialize-WinUtilFaviconRunspacePool {
<#
.SYNOPSIS
Creates or returns the dedicated runspace pool used for favicon downloads.
.DESCRIPTION
Uses the machine's available logical processor count, with a minimum of one
worker. The pool remains dedicated to favicon downloads so this work stays
isolated from other WinUtil runspaces.
#>
if ($sync.FaviconRunspace -and $sync.FaviconRunspace.RunspacePoolStateInfo.State -eq [System.Management.Automation.Runspaces.RunspacePoolState]::Opened) {
return $sync.FaviconRunspace
}

if ($sync.FaviconRunspace) {
try {
if ($sync.FaviconRunspace.RunspacePoolStateInfo.State -notin @(
[System.Management.Automation.Runspaces.RunspacePoolState]::Closed,
[System.Management.Automation.Runspaces.RunspacePoolState]::Closing,
[System.Management.Automation.Runspaces.RunspacePoolState]::Broken
)) {
$sync.FaviconRunspace.Close()
}
} finally {
$sync.FaviconRunspace.Dispose()
$sync.Remove("FaviconRunspace")
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

$maxThreads = [Environment]::ProcessorCount
$initialSessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()

$sync.FaviconRunspace = [runspacefactory]::CreateRunspacePool(
1,
$maxThreads,
$initialSessionState,
$Host
)
$sync.FaviconRunspace.Open()
return $sync.FaviconRunspace
}
Loading