feat(tui): add fzf-based folder browser for export/import path prompts

Read-Host has no tab-completion (that's a top-level PSReadLine feature,
not available to script prompts), so reuse the fzf dependency already
required for menus to browse folders interactively instead: navigate
into subfolders, go up with .., confirm current folder, or type a path
manually. Falls back to plain Read-Host when fzf isn't installed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-07 11:53:05 +02:00
parent 30170a1909
commit 81c5e96fc7
4 changed files with 49 additions and 7 deletions
+7
View File
@@ -1,5 +1,12 @@
# macOS Intune Toolkit Changelog
## 2026-08-07 — v4.4.0 — Folder browser for Export/Import path prompts
### Added
- **`Scripts/Private/Start-IntuneManagementTui.ps1`**
- New `Select-FolderPath` helper: when `fzf` is available, the Export/Import root folder prompt (and the report flow's export/backup-root/output-dir prompts) becomes an interactive folder browser — navigate into subfolders, go up with `..`, confirm the current folder, or type a path manually. `Read-Host` alone has no tab-completion (that's a top-level PSReadLine feature, not available to script prompts), so this reuses the `fzf` dependency already required for menus instead of building custom completion.
- Falls back to a plain `Read-Host` prompt when `fzf` isn't installed — no regression from prior behavior.
## 2026-08-07 — v4.3.1 — Fix redundant action prompt
### Fixed
+1 -1
View File
@@ -2,7 +2,7 @@
Cross-platform, headless Intune policy export/import with PowerShell.
**Current version:** `4.3.1` — see [`CHANGELOG_macOS_IntuneToolkit.md`](CHANGELOG_macOS_IntuneToolkit.md) for recent changes.
**Current version:** `4.4.0` — see [`CHANGELOG_macOS_IntuneToolkit.md`](CHANGELOG_macOS_IntuneToolkit.md) for recent changes.
This repository is now CLI-first. The old WPF application surface has been removed from the repo. The supported workflow is:
+40 -5
View File
@@ -107,6 +107,41 @@ function Select-MenuItem
return Show-NumberedMenu -Items $Items -Header $Header -Multi:$Multi
}
function Select-FolderPath
{
param(
[Parameter(Mandatory)]
[string]$Prompt,
[string]$StartPath = (Get-Location).Path
)
if(-not (Test-FzfAvailable))
{
return Read-Host $Prompt
}
$current = if(Test-Path -LiteralPath $StartPath) { (Resolve-Path -LiteralPath $StartPath).Path } else { (Get-Location).Path }
while($true)
{
$entries = @("[Use this folder]", "[Type path manually]")
$parent = Split-Path -Path $current -Parent
if($parent) { $entries += ".." }
$subdirs = Get-ChildItem -LiteralPath $current -Directory -ErrorAction SilentlyContinue | Sort-Object Name | ForEach-Object { "$($_.Name)/" }
$entries += $subdirs
$choice = $entries | fzf --header="$Prompt [current: $current]"
if(-not $choice) { return $null }
switch ($choice)
{
"[Use this folder]" { return $current }
"[Type path manually]" { $typed = Read-Host "Enter path"; if(-not [string]::IsNullOrWhiteSpace($typed)) { return $typed }; continue }
".." { $current = $parent; continue }
default { $current = Join-Path $current ($choice.TrimEnd('/')); continue }
}
}
}
function Read-YesNo
{
param(
@@ -275,18 +310,18 @@ while($true)
if([string]::IsNullOrWhiteSpace($tenantIdForReport)) { Write-Host "Tenant ID is required." -ForegroundColor Red; continue }
}
$exportPath = Read-Host "Export path (where to save fresh data)"
$exportPath = Select-FolderPath -Prompt "Select export path (where to save fresh data)"
if([string]::IsNullOrWhiteSpace($exportPath)) { Write-Host "Export path is required." -ForegroundColor Red; continue }
$backupRoot = $exportPath
}
else
{
$backupRoot = Read-Host "Backup root path (folder containing 'Settings Catalog', etc.)"
$backupRoot = Select-FolderPath -Prompt "Select backup root (folder containing 'Settings Catalog', etc.)"
if([string]::IsNullOrWhiteSpace($backupRoot)) { Write-Host "Backup root is required." -ForegroundColor Red; continue }
if(-not (Test-Path $backupRoot)) { Write-Host "Path not found: $backupRoot" -ForegroundColor Red; continue }
}
$outputDir = Read-Host "Enter output directory for reports"
$outputDir = Select-FolderPath -Prompt "Select output directory for reports"
if([string]::IsNullOrWhiteSpace($outputDir)) { Write-Host "Output directory is required." -ForegroundColor Red; continue }
$includeAssignmentsInSettings = $false
@@ -358,8 +393,8 @@ while($true)
if(-not $typeSelection) { continue }
# 4. Path
$pathPrompt = if($action -eq "Export") { "Enter export root folder path" } else { "Enter import root folder path" }
$path = Read-Host $pathPrompt
$pathPrompt = if($action -eq "Export") { "Select export root folder" } else { "Select import root folder" }
$path = Select-FolderPath -Prompt $pathPrompt
if([string]::IsNullOrWhiteSpace($path)) { Write-Host "Path is required." -ForegroundColor Red; return $null }
# 5. Name Filter
+1 -1
View File
@@ -1 +1 @@
4.3.1
4.4.0