src/UI/05-Welcome.ps1
|
# 05-Welcome.ps1 - the first-run welcome overlay: a new user has no reason # to guess that 'g' hides the whole navigation layer, so the very first grid # paint gets a small tips panel floating over it (same VT overlay as goto). # Shown exactly once, ever - a marker file next to the main config remembers # it (so $PSMM_MainConfigPath redirects it too, like the update-check cache). function script:Get-PSMMWelcomePath { [CmdletBinding()] param() Join-Path (Split-Path -Parent (Get-PSMMMainConfigPath)) 'psmm-welcome.json' } function script:Test-PSMMWelcomeDue { [CmdletBinding()][OutputType([bool])] param() -not (Test-Path -LiteralPath (Get-PSMMWelcomePath) -ErrorAction Ignore) } function script:Set-PSMMWelcomeShown { [CmdletBinding()] param() $p = Get-PSMMWelcomePath try { $dir = Split-Path -Parent $p if (-not (Test-Path -LiteralPath $dir -ErrorAction Ignore)) { $null = New-Item -ItemType Directory -Path $dir -Force -ErrorAction Stop } @{ ShownAt = [datetime]::UtcNow.ToString('o') } | ConvertTo-Json | Set-Content -LiteralPath $p -Encoding utf8 -ErrorAction Stop } catch { } # an unwritable config dir must never break the TUI } # The panel: three tips, g first - that is the key nobody would guess. function script:Build-PSMMWelcomePanel { $tips = @( @{ Key = 'g'; Label = 'goto'; Text = 'then a letter jumps to any screen, from anywhere' } @{ Key = '?'; Label = 'help'; Text = 'keys and tips for the screen you are on' } @{ Key = 'enter'; Label = 'actions'; Text = 'everything psmm can do with the highlighted module' } ) $g = [Spectre.Console.Grid]::new() for ($c = 0; $c -lt 2; $c++) { $col = [Spectre.Console.GridColumn]::new() $col.Padding = [Spectre.Console.Padding]::new(0, 0, 2, 0) [void]$g.AddColumn($col) } foreach ($t in $tips) { [void][Spectre.Console.GridExtensions]::AddRow($g, [string[]]@( "[$script:PSMM_ColKey on $script:PSMM_ColCapsuleDim] $($t.Key) [/] [$script:PSMM_ColMute]$($t.Label)[/]", "[$script:PSMM_ColDim]$($t.Text)[/]")) } $items = [System.Collections.Generic.List[Spectre.Console.Rendering.IRenderable]]::new() $items.Add([Spectre.Console.Markup]::new( "[$script:PSMM_ColBrandFg on $script:PSMM_ColBrandBg] psmm [/] [default]welcome[/] [$script:PSMM_ColDim]$([char]0x2014) the three keys worth knowing[/]")) $items.Add($g) $items.Add([Spectre.Console.Markup]::new( "[$script:PSMM_ColDim]any key closes this $([char]0x00B7) it appears only once[/]")) $panel = [Spectre.Console.Panel]::new([Spectre.Console.Rows]::new($items)) $panel.Border = [Spectre.Console.BoxBorder]::Rounded $panel.BorderStyle = [Spectre.Console.Style]::Parse($script:PSMM_ColAccent) $panel } # Float the panel over the current frame, wait for one key, restore. The # marker is only written when the panel was actually seen; headless hosts # skip everything (mirrors Write-PSMMOverlay's redirected-output no-op). function script:Show-PSMMWelcomeOverlay { [CmdletBinding()] param($BaseRenderable) if ([Console]::IsOutputRedirected -or [Console]::IsInputRedirected) { return } $region = Write-PSMMOverlay -Renderable (Build-PSMMWelcomePanel) -Content $BaseRenderable $k = [Console]::ReadKey($true) Clear-PSMMOverlay -Region $region Set-PSMMWelcomeShown if (Test-PSMMHardQuitKey $k) { $script:PSMM_UI.HardQuit = $true } } |