mirror of
https://github.com/ChrisTitusTech/winutil.git
synced 2026-08-10 01:51:18 +10:00
* Add Quick Category Search Chips to Install tab Add category shortcut chips on the Install tab that insert the category name into the existing search box. Append each app's category as a description tag so the existing description search filters by category. Reuses the standard button style and existing search; no search, install, or preset logic is changed. * Fix install category chip filtering * Fix category filter refresh behavior --------- Co-authored-by: Chris Titus <contact@christitus.com>
144 lines
6.2 KiB
PowerShell
144 lines
6.2 KiB
PowerShell
function Find-AppsByNameOrDescription {
|
|
<#
|
|
.SYNOPSIS
|
|
Searches through the Apps on the Install Tab and hides all entries that do not match the string
|
|
|
|
.DESCRIPTION
|
|
Filters application entries by name or description using literal string matching.
|
|
Respects collapsed category state and handles null $sync gracefully.
|
|
|
|
.PARAMETER SearchString
|
|
The string to be searched for. Wildcards are treated as literal characters.
|
|
|
|
.PARAMETER Category
|
|
When provided, only applications in this exact category are shown.
|
|
|
|
.NOTES
|
|
- Uses module-scope $sync (no parameter needed; inherits from caller's scope)
|
|
- Performs literal matching (no wildcard expansion)
|
|
- Safely handles missing hashtable keys and null UI elements
|
|
- Protected by try/catch to prevent UI thread crashes
|
|
#>
|
|
param(
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$SearchString = "",
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$Category = ""
|
|
)
|
|
|
|
# Validate that $sync exists and has required structure
|
|
if ($null -eq $sync) {
|
|
Write-Warning "Find-AppsByNameOrDescription: Global `$sync not found. Aborting search."
|
|
return
|
|
}
|
|
|
|
if ($null -eq $sync.ItemsControl) {
|
|
Write-Warning "Find-AppsByNameOrDescription: `$sync.ItemsControl not initialized. Aborting search."
|
|
return
|
|
}
|
|
|
|
if ($null -eq $sync.configs -or $null -eq $sync.configs.applicationsHashtable) {
|
|
Write-Warning "Find-AppsByNameOrDescription: `$sync.configs.applicationsHashtable not initialized. Aborting search."
|
|
return
|
|
}
|
|
|
|
try {
|
|
# Reset the visibility if the search string is empty or the search is cleared
|
|
if ([string]::IsNullOrWhiteSpace($SearchString) -and [string]::IsNullOrWhiteSpace($Category)) {
|
|
$sync.ItemsControl.Items | ForEach-Object {
|
|
# Each item is a StackPanel container
|
|
$_.Visibility = [Windows.Visibility]::Visible
|
|
|
|
if ($_.Children.Count -ge 2) {
|
|
$categoryLabel = $_.Children[0]
|
|
$wrapPanel = $_.Children[1]
|
|
|
|
# Keep category label visible
|
|
$categoryLabel.Visibility = [Windows.Visibility]::Visible
|
|
|
|
# Respect the collapsed state of categories (indicated by + prefix)
|
|
if ($categoryLabel.Content -like "+*") {
|
|
$wrapPanel.Visibility = [Windows.Visibility]::Collapsed
|
|
}
|
|
else {
|
|
$wrapPanel.Visibility = [Windows.Visibility]::Visible
|
|
}
|
|
|
|
# Show all apps within the category
|
|
$wrapPanel.Children | ForEach-Object {
|
|
$_.Visibility = [Windows.Visibility]::Visible
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
# Escape wildcard characters for literal matching
|
|
$escapedSearchString = [System.Management.Automation.WildcardPattern]::Escape($SearchString)
|
|
|
|
# Perform search
|
|
$sync.ItemsControl.Items | ForEach-Object {
|
|
# Each item is a StackPanel container with Children[0] = label, Children[1] = WrapPanel
|
|
if ($_.Children.Count -ge 2) {
|
|
$categoryLabel = $_.Children[0]
|
|
$wrapPanel = $_.Children[1]
|
|
$categoryHasMatch = $false
|
|
|
|
# Keep category label visible
|
|
$categoryLabel.Visibility = [Windows.Visibility]::Visible
|
|
|
|
# Search through apps in this category
|
|
foreach ($appControl in $wrapPanel.Children) {
|
|
# Safely retrieve app entry from hashtable
|
|
$appTag = $appControl.Tag
|
|
$appEntry = $null
|
|
|
|
if (-not [string]::IsNullOrWhiteSpace($appTag) -and $sync.configs.applicationsHashtable.ContainsKey($appTag)) {
|
|
$appEntry = $sync.configs.applicationsHashtable[$appTag]
|
|
}
|
|
|
|
# Check if app matches search criteria
|
|
if ($null -ne $appEntry) {
|
|
$categoryMatch = -not [string]::IsNullOrWhiteSpace($Category) -and $appEntry.Category -eq $Category
|
|
$contentMatch = [string]::IsNullOrWhiteSpace($Category) -and $appEntry.Content -like "*$escapedSearchString*"
|
|
$descriptionMatch = [string]::IsNullOrWhiteSpace($Category) -and $appEntry.Description -like "*$escapedSearchString*"
|
|
|
|
if ($categoryMatch -or $contentMatch -or $descriptionMatch) {
|
|
# Show the App and mark that this category has a match
|
|
$appControl.Visibility = [Windows.Visibility]::Visible
|
|
$categoryHasMatch = $true
|
|
}
|
|
else {
|
|
$appControl.Visibility = [Windows.Visibility]::Collapsed
|
|
}
|
|
}
|
|
else {
|
|
# Hide app if no entry found (data integrity issue)
|
|
$appControl.Visibility = [Windows.Visibility]::Collapsed
|
|
}
|
|
}
|
|
|
|
# If category has matches, show the WrapPanel and update the category label to expanded state
|
|
if ($categoryHasMatch) {
|
|
$wrapPanel.Visibility = [Windows.Visibility]::Visible
|
|
$_.Visibility = [Windows.Visibility]::Visible
|
|
# Update category label to show expanded state (-)
|
|
if ($categoryLabel.Content -like "+*") {
|
|
$categoryLabel.Content = $categoryLabel.Content -replace "^\+ ", "- "
|
|
}
|
|
}
|
|
else {
|
|
# Hide the entire category container if no matches
|
|
$_.Visibility = [Windows.Visibility]::Collapsed
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch {
|
|
Write-Warning "Find-AppsByNameOrDescription: An error occurred during search: $_"
|
|
# Fail gracefully - do not crash the UI thread
|
|
return
|
|
}
|
|
}
|