Files
winutil/functions/private/Find-TweaksByNameOrDescription.ps1
T
GabiandGitHub 7c71a39f7a Feature/appx removal tab (#4729)
* feat: add config-driven AppX package removal tab

- Add config/appx.json with curated list of removable AppX packages

- Add AppX Removal tab (WPFTab6) with Select All, Clear, and Remove buttons

- Reuse existing Invoke-WPFUIElements engine for minimal code footprint

- Add Invoke-WPFAppxRemoval.ps1 for background runspace package removal

- Add theme colors for the new tab button in light and dark modes

* yep

* yep

* yep

* yep

* Update inputXML.xaml

* Update Invoke-WPFButton.ps1

* Update Invoke-WPFButton.ps1

* Update Invoke-WPFSelectedCheckboxesUpdate.ps1

* Update appx.json

* Update appx.json

* Update appx.json

* Update tweaks.json

* Update appx.json

* Update appx.json

* Update appx.json

* Update Invoke-WPFAppxRemoval.ps1

* Update Invoke-WPFButton.ps1

* Delete functions/public/Invoke-WPFAppxRemoval.ps1

* Revert "Update Invoke-WPFButton.ps1"

This reverts commit d8705cc08e.

* Revert "Delete functions/public/Invoke-WPFAppxRemoval.ps1"

This reverts commit 9e45d1ad99.

* Update Invoke-WPFAppxRemoval.ps1

* Update Invoke-WPFAppxRemoval.ps1

* Update Invoke-WPFAppxRemoval.ps1

* Update Invoke-WPFButton.ps1

* yep

* Update appx.json

* Update appx.json

* Update tweaks.json

* Update start.ps1

* Update preset.json

* Update tweaks.json

* yep

* yep

* yep

* yep

* yep

* yep

* Update Invoke-WPFAppxRemoval.ps1

* Update Update-WinUtilSelections.ps1

* Update Update-WinUtilSelections.ps1

* yep

* Update Invoke-WPFAppxRemoval.ps1

* yep

* yep

* Update Invoke-WPFAppxRemoval.ps1

* Update appx.json

* Update Invoke-WPFAppxRemoval.ps1

* Update Invoke-WPFAppxRemoval.ps1

* Update appx.json

* Update Invoke-WPFGetInstalled.ps1

* Update Invoke-WPFAppxRemoval.ps1

* yep

* yep

* Update Invoke-WPFSelectedCheckboxesUpdate.ps1

* yep

* yep

* Update Invoke-WPFAppxRemoval.ps1

* Update Invoke-WPFAppxRemoval.ps1

* yep

* Update Invoke-WPFAppxRemoval.ps1

* Update Invoke-WPFAppxRemoval.ps1

* Update appx.json

* Update Invoke-WPFImpex.ps1

* Update Invoke-WPFImpex.ps1

* Update Invoke-WPFAppxRemoval.ps1

* Update preset.json

* Update preset.json

* Update Invoke-WPFSelectedCheckboxesUpdate.ps1

* Update Invoke-WPFAppxRemoval.ps1

* Update tweaks.json

* Update Invoke-WPFAppxRemoval.ps1

* Update Invoke-WPFAppxRemoval.ps1

* Update Invoke-WPFAppxRemoval.ps1

* Update Invoke-WPFAppxRemoval.ps1

* yep

* yep

* Update Invoke-WPFAppxRemoval.ps1

* yep

* Delete functions/private/Find-AppxByNameOrDescription.ps1

* yep

* Update Invoke-WPFButton.ps1

* Update main.ps1

* Update Invoke-WPFTab.ps1

* yep

* yep

* Update themes.json
2026-07-01 12:13:32 -05:00

308 lines
14 KiB
PowerShell

function Find-TweaksByNameOrDescription {
<#
.SYNOPSIS
Searches through the Tweaks on the Tweaks Tab and hides all entries that do not match the search string
.DESCRIPTION
Filters tweak entries by name or description using literal string matching (no wildcard expansion).
Respects collapsed category state and handles null $sync gracefully.
Safe for rapid keystroke events; no terminal spam on error conditions.
.PARAMETER SearchString
The string to be searched for. Wildcards are treated as literal characters.
.NOTES
- Uses module-scope $sync (resolved via global/script fallback if needed)
- Performs literal matching (no wildcard expansion)
- Safely handles missing UI elements and null properties
- Protected by try/catch to prevent UI thread crashes
- PowerShell 5.1 compatible (no ternary operators, no advanced language features)
#>
param(
[Parameter(Mandatory = $false)]
[string]$SearchString = ""
)
# ------------------------------------------------------------------------------
# 1. RESOLVE $SYNC WITH MULTI-LEVEL FALLBACK
# ------------------------------------------------------------------------------
if ($null -eq $Sync) {
$Sync = $global:sync
if ($null -eq $Sync) {
$Sync = $script:sync
}
}
# Validate that $Sync exists and has required structure
if ($null -eq $Sync) {
# Silent return - function called on every keystroke; no warning spam
return
}
if ($null -eq $Sync.Form) {
# Silent return - form not yet initialized
return
}
# ------------------------------------------------------------------------------
# 2. GET REFERENCE TO TWEAKS OR APPX PANEL
# ------------------------------------------------------------------------------
$panelName = "tweakspanel"
if ($null -ne $Sync.currentTab -and $Sync.currentTab -eq "AppX") {
$panelName = "appxpanel"
}
$tweaksPanel = $null
try {
$tweaksPanel = $Sync.Form.FindName($panelName)
}
catch {
# Silent return - panel not found or disposed
return
}
if ($null -eq $tweaksPanel) {
# Silent return - panel doesn't exist
return
}
# ------------------------------------------------------------------------------
# 3. HANDLE EMPTY/WHITESPACE SEARCH STRING - RESET TO DEFAULT STATE
# ------------------------------------------------------------------------------
if ([string]::IsNullOrWhiteSpace($SearchString)) {
try {
$tweaksPanel.Children | ForEach-Object {
$categoryBorder = $_
# Safely set visibility
if ($null -ne $categoryBorder) {
$categoryBorder.Visibility = [Windows.Visibility]::Visible
}
# Process each category
if ($categoryBorder -is [Windows.Controls.Border]) {
$dockPanel = $null
if ($null -ne $categoryBorder.Child) {
$dockPanel = $categoryBorder.Child
}
if ($dockPanel -is [Windows.Controls.DockPanel]) {
$itemsControl = $null
$itemsControl = $dockPanel.Children | Where-Object { $_ -is [Windows.Controls.ItemsControl] } | Select-Object -First 1
if ($null -ne $itemsControl) {
# Show all items in the category
foreach ($item in $itemsControl.Items) {
if ($null -ne $item) {
# Check if it's a category label (first Label in the ItemsControl)
if ($item -is [Windows.Controls.Label]) {
$item.Visibility = [Windows.Visibility]::Visible
}
elseif ($item -is [Windows.Controls.DockPanel] -or $item -is [Windows.Controls.StackPanel]) {
# Show all checkbox containers
$item.Visibility = [Windows.Visibility]::Visible
}
}
}
}
}
}
}
}
catch {
# Silent catch - UI element may be disposed
}
return
}
# ------------------------------------------------------------------------------
# 4. PERFORM LITERAL SEARCH (NO WILDCARD EXPANSION)
# ------------------------------------------------------------------------------
try {
# Normalize search term once for the entire operation
$searchTerm = $SearchString
if ($null -eq $searchTerm) {
$searchTerm = ""
}
# Iterate through all categories
$tweaksPanel.Children | ForEach-Object {
$categoryBorder = $_
$categoryHasMatch = $false
if ($categoryBorder -is [Windows.Controls.Border]) {
$dockPanel = $null
if ($null -ne $categoryBorder.Child) {
$dockPanel = $categoryBorder.Child
}
if ($dockPanel -is [Windows.Controls.DockPanel]) {
$itemsControl = $null
$itemsControl = $dockPanel.Children | Where-Object { $_ -is [Windows.Controls.ItemsControl] } | Select-Object -First 1
if ($null -ne $itemsControl) {
$categoryLabel = $null
# Process all items (checkboxes, labels, panels) in the ItemsControl
for ($i = 0; $i -lt $itemsControl.Items.Count; $i++) {
$item = $itemsControl.Items[$i]
if ($null -eq $item) {
continue
}
# ------------------------------------------------------------
# Check if this is a category label (usually first Label)
# ------------------------------------------------------------
if ($item -is [Windows.Controls.Label]) {
$categoryLabel = $item
# Initially hide category label; show it only if matches found
$item.Visibility = [Windows.Visibility]::Collapsed
}
# ------------------------------------------------------------
# Check if this is a DockPanel containing a tweak checkbox
# ------------------------------------------------------------
elseif ($item -is [Windows.Controls.DockPanel]) {
$checkbox = $null
$label = $null
# Safely extract checkbox and label
$checkbox = $item.Children | Where-Object { $_ -is [Windows.Controls.CheckBox] } | Select-Object -First 1
$label = $item.Children | Where-Object { $_ -is [Windows.Controls.Label] } | Select-Object -First 1
# Check if tweak matches search criteria
$itemMatches = $false
if ($null -ne $label) {
$labelContent = $label.Content
$labelToolTip = $label.ToolTip
# Safely null-check properties
if ($null -eq $labelContent) {
$labelContent = ""
}
if ($null -eq $labelToolTip) {
$labelToolTip = ""
}
# Convert to string and perform LITERAL matching
$labelContentStr = [string]$labelContent
$labelToolTipStr = [string]$labelToolTip
# Use IndexOf for literal matching (no wildcard interpretation)
$contentMatch = $labelContentStr.IndexOf($searchTerm, [System.StringComparison]::OrdinalIgnoreCase) -ge 0
$toolTipMatch = $labelToolTipStr.IndexOf($searchTerm, [System.StringComparison]::OrdinalIgnoreCase) -ge 0
if ($contentMatch -or $toolTipMatch) {
$itemMatches = $true
}
}
# Set visibility based on match result
if ($itemMatches) {
$item.Visibility = [Windows.Visibility]::Visible
$categoryHasMatch = $true
}
else {
$item.Visibility = [Windows.Visibility]::Collapsed
}
}
# ------------------------------------------------------------
# Check if this is a StackPanel containing a tweak checkbox
# ------------------------------------------------------------
elseif ($item -is [Windows.Controls.StackPanel]) {
$checkbox = $null
$checkbox = $item.Children | Where-Object { $_ -is [Windows.Controls.CheckBox] } | Select-Object -First 1
$itemMatches = $false
if ($null -ne $checkbox) {
$checkboxContent = $checkbox.Content
$checkboxToolTip = $checkbox.ToolTip
# Safely null-check properties
if ($null -eq $checkboxContent) {
$checkboxContent = ""
}
if ($null -eq $checkboxToolTip) {
$checkboxToolTip = ""
}
# Convert to string and perform LITERAL matching
$checkboxContentStr = [string]$checkboxContent
$checkboxToolTipStr = [string]$checkboxToolTip
# Use IndexOf for literal matching (no wildcard interpretation)
$contentMatch = $checkboxContentStr.IndexOf($searchTerm, [System.StringComparison]::OrdinalIgnoreCase) -ge 0
$toolTipMatch = $checkboxToolTipStr.IndexOf($searchTerm, [System.StringComparison]::OrdinalIgnoreCase) -ge 0
if ($contentMatch -or $toolTipMatch) {
$itemMatches = $true
}
}
# Set visibility based on match result
if ($itemMatches) {
$item.Visibility = [Windows.Visibility]::Visible
$categoryHasMatch = $true
}
else {
$item.Visibility = [Windows.Visibility]::Collapsed
}
}
}
# ------------------------------------------------------------
# Update category label visibility and expanded/collapsed state
# ------------------------------------------------------------
if ($categoryHasMatch) {
# Show category label
if ($null -ne $categoryLabel) {
$categoryLabel.Visibility = [Windows.Visibility]::Visible
# Update category label to expanded state (change "+" to "-")
$labelContent = $categoryLabel.Content
if ($null -ne $labelContent) {
$labelStr = [string]$labelContent
# Safe string replacement without -replace regex
if ($labelStr.StartsWith("+ ")) {
$expandedLabel = "- " + $labelStr.Substring(2)
$categoryLabel.Content = $expandedLabel
}
}
}
}
}
}
# ----------------------------------------------------------------
# Set category border visibility based on whether it has matches
# ----------------------------------------------------------------
if ($categoryHasMatch) {
$categoryBorder.Visibility = [Windows.Visibility]::Visible
}
else {
$categoryBorder.Visibility = [Windows.Visibility]::Collapsed
}
}
}
}
catch {
# Silent catch - UI elements may be disposed or in unexpected state
# Do not log to terminal as this function is called on every keystroke
}
}