Skip to content

Commit 8f9c1d1

Browse files
committed
Refine VSCodeUpdaterGUI layout and integrate new helpers
- Rework GUI layout (status, task viewer, command window, log viewer) - Add OutputHelpers.ps1 for shared formatting/output routines - Update version management and rollback/safe mode logic - Improve Switch-VSCodeVersions and Invoke-VSCodeRollback flows - Expand GUI test coverage for new layout structure - Sync.ps1 improvements for module consistency - Update module manifest and root module exports
1 parent b26b7f2 commit 8f9c1d1

11 files changed

Lines changed: 555 additions & 257 deletions

GUI/Start-VSCodeUpdaterGUI.ps1

Lines changed: 254 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@
1111
Version: 1.0.0
1212
Description: Description goes here
1313
#>
14+
# NOW import the module
15+
Remove-Module VSCode-Updater -ErrorAction SilentlyContinue
1416
Import-Module "$PSScriptRoot\..\VSCode-Updater.psd1" -Force
17+
# Load output helpers (this defines _out)
18+
. "$PSScriptRoot\..\Private\OutputHelpers.ps1"
19+
. "$PSScriptRoot\..\Private\Write-Log.ps1"
20+
1521

1622
function Get-SelectedVersionName {
1723
[CmdletBinding()]
@@ -31,6 +37,105 @@ function Get-SelectedVersionName {
3137

3238
return $null
3339
}
40+
function Clear-Terminal {
41+
$window.Dispatcher.Invoke({
42+
$txtCommandOutput.Document.Blocks.Clear()
43+
})
44+
}
45+
function Confirm-SetupAppRunning {
46+
$proc = Get-Process -Name "SetupApp" -ErrorAction SilentlyContinue
47+
48+
if (-not $proc) {
49+
Write-TaskViewerLine "SetupApp missing — restarting..." "Yellow"
50+
51+
try {
52+
Start-Process "C:\Path\To\SetupApp.exe"
53+
Write-TaskViewerLine "SetupApp restarted successfully." "LightGreen"
54+
}
55+
catch {
56+
Write-TaskViewerLine "Failed to restart SetupApp: $_" "Red"
57+
}
58+
}
59+
}
60+
function Invoke-StreamingCommand {
61+
param([string]$Command)
62+
63+
Clear-Terminal
64+
Write-TerminalLine "Running: $Command" "LightBlue"
65+
66+
$psi = New-Object System.Diagnostics.ProcessStartInfo
67+
$psi.FileName = "powershell.exe"
68+
$psi.Arguments = "-NoLogo -NoProfile -Command $Command"
69+
$psi.RedirectStandardOutput = $true
70+
$psi.RedirectStandardError = $true
71+
$psi.UseShellExecute = $false
72+
$psi.CreateNoWindow = $true
73+
74+
$proc = New-Object System.Diagnostics.Process
75+
$proc.StartInfo = $psi
76+
77+
# Hook stdout
78+
$proc.add_OutputDataReceived({
79+
if ($_.Data) {
80+
Write-TerminalLine $_.Data "White"
81+
}
82+
})
83+
84+
# Hook stderr
85+
$proc.add_ErrorDataReceived({
86+
if ($_.Data) {
87+
Write-TerminalLine $_.Data "Red"
88+
}
89+
})
90+
91+
$proc.Start()
92+
$proc.BeginOutputReadLine()
93+
$proc.BeginErrorReadLine()
94+
95+
# Optional: wait for completion without blocking UI
96+
Start-Job -ScriptBlock {
97+
$proc.WaitForExit()
98+
$window.Dispatcher.Invoke({
99+
Write-TerminalLine "Process exited with code $($proc.ExitCode)" "LightGray"
100+
})
101+
}
102+
}
103+
function Show-DashboardInTerminal {
104+
$info = Get-VSCodeDashboard
105+
106+
Write-TerminalLine "=== Dashboard ===" "LightGray"
107+
108+
if ($info) {
109+
Write-TerminalLine "Installed Versions: $($info.InstalledVersions)" "White"
110+
Write-TerminalLine "Version Count: $($info.VersionCount)" "White"
111+
Write-TerminalLine "Active Version: $($info.ActiveVersion)" "Green"
112+
Write-TerminalLine "Cache Path: $($info.CachePath)" "Yellow"
113+
Write-TerminalLine "LastUpdateLog: $($info.LastUpdateLog)" "White"
114+
}
115+
else {
116+
Write-TerminalLine "Dashboard: No information available." "Red"
117+
}
118+
119+
Write-TerminalLine "=================" "LightGray"
120+
}
121+
function Show-VSCodeSymlinkInfo {
122+
$info = Get-VSCodeSymlinkInfo
123+
124+
Write-TerminalLine "=== VSCode Symlink Info ===" "LightGray"
125+
126+
if ($info) {
127+
Write-TerminalLine "Active Version: $($info.ActiveVersion)" "LightGreen"
128+
Write-TerminalLine "Target Path: $($info.TargetPath)" "White"
129+
Write-TerminalLine "Valid: $($info.IsValid)" "LightBlue"
130+
Write-TerminalLine "Last Update: $($info.LastUpdateResult)" "Yellow"
131+
Write-TerminalLine "Fallback Reason:$($info.LastFallbackReason)" "Red"
132+
}
133+
else {
134+
Write-TerminalLine "No symlink information found." "Red"
135+
}
136+
137+
Write-TerminalLine "=============================" "LightGray"
138+
}
34139

35140
function Start-VSCodeUpdaterGUI {
36141

@@ -39,6 +144,7 @@ function Start-VSCodeUpdaterGUI {
39144
Add-Type -AssemblyName PresentationCore
40145
Add-Type -AssemblyName WindowsBase
41146

147+
$script:SafeMode = $false
42148

43149
# Resolve XAML path relative to the Public folder
44150
$xamlPath = Join-Path $PSScriptRoot "VSCodeUpdaterGUI.xaml"
@@ -58,21 +164,37 @@ function Start-VSCodeUpdaterGUI {
58164
$stream.Position = 0
59165

60166
$reader = [System.Xml.XmlReader]::Create($stream)
61-
$window = [Windows.Markup.XamlReader]::Load($reader)
167+
$global:window = [Windows.Markup.XamlReader]::Load($reader)
62168

63169
$dgVersions = $window.FindName("DgVersions")
64170

65171
# Bind controls
66-
$btnUpdate = $window.FindName("BtnUpdate")
67-
$btnRollback = $window.FindName("BtnRollback")
68-
$btnSwitch = $window.FindName("BtnSwitch")
69-
$txtStatus = $window.FindName("TxtStatus")
70-
$txtLog = $window.FindName("TxtLog")
71-
$txtActiveVersion = $window.FindName("TxtActiveVersion")
72-
$txtSymlinkTarget = $window.FindName("TxtSymlinkTarget")
73-
$txtSymlinkValid = $window.FindName("TxtSymlinkValid")
74-
$txtLastUpdate = $window.FindName("TxtLastUpdate")
75-
$txtFallbackReason = $window.FindName("TxtFallbackReason")
172+
$script:btnUpdate = $window.FindName("BtnUpdate")
173+
$script:btnRollback = $window.FindName("BtnRollback")
174+
$script:btnSwitch = $window.FindName("BtnSwitch")
175+
$script:txtStatus = $window.FindName("TxtStatus")
176+
$script:txtLog = $window.FindName("TxtLog")
177+
$global:txtCommandOutput = $window.FindName("TxtCommandOutput")
178+
$script:txtActiveVersion = $window.FindName("TxtActiveVersion")
179+
$script:txtSymlinkTarget = $window.FindName("TxtSymlinkTarget")
180+
$script:txtSymlinkValid = $window.FindName("TxtSymlinkValid")
181+
$script:txtLastUpdate = $window.FindName("TxtLastUpdate")
182+
$script:txtFallbackReason = $window.FindName("TxtFallbackReason")
183+
$script:btnValidateSymlink = $window.FindName("BtnValidateSymlink")
184+
$script:btnSafeMode = $window.FindName("BtnSafeMode")
185+
$script:btnDashboard = $window.FindName("BtnDashboard")
186+
$script:btnPauseLog = $window.FindName("BtnPauseLog")
187+
$script:btnSearchLog = $window.FindName("BtnSearchLog")
188+
$script:chkAutoScroll = $window.FindName("ChkAutoScroll")
189+
$script:txtSearchLog = $window.FindName("TxtSearchLog")
190+
$script:txtTaskViewer = $window.FindName("TxtTaskViewer") # if present
191+
$script:btnRestartSetup = $window.FindName("BtnRestartSetup")
192+
$script:chkSafeMode = $window.FindName("ChkSafeMode")
193+
# Default Safe Mode state on load
194+
$script:SafeMode = $true
195+
$chkSafeMode.IsChecked = $true
196+
197+
$txtTaskViewer.Document = New-Object System.Windows.Documents.FlowDocument
76198

77199
$info = Get-VSCodeSymlinkInfo
78200
$window.Resources["ActiveVersionName"] = $info.ActiveVersion
@@ -95,14 +217,22 @@ function Start-VSCodeUpdaterGUI {
95217
if (Test-Path $LogFile) {
96218
try {
97219
$txtLog.Text = (Get-Content $LogFile -Tail 200) -join "`r`n"
98-
$txtLog.ScrollToEnd()
220+
221+
if ($chkAutoScroll.IsChecked) {
222+
$txtLog.ScrollToEnd()
223+
}
99224
}
100225
catch {
101226
# Ignore transient file locks
102227
}
103228
}
104229
})
105230
$timer.Start()
231+
$taskTimer = New-Object Windows.Threading.DispatcherTimer
232+
$taskTimer.Interval = [TimeSpan]::FromSeconds(5)
233+
$taskTimer.Add_Tick({ Update-TaskViewerStatus })
234+
$taskTimer.Start()
235+
106236
# --------------------------------
107237

108238
# Load version list
@@ -131,7 +261,10 @@ function Start-VSCodeUpdaterGUI {
131261
$btnUpdate.Add_Click({
132262
$result = Update-VSCode
133263
$txtStatus.Text = "Update completed: $result"
134-
Update-VersionList
264+
})
265+
266+
$btnRestartSetup.Add_Click({
267+
Confirm-SetupAppRunning
135268
})
136269

137270
$btnRollback.Add_Click({
@@ -161,6 +294,7 @@ function Start-VSCodeUpdaterGUI {
161294
$result = Test-VSCodeSymlink
162295
$txtStatus.Text = "Symlink validation: $result"
163296
Update-SymlinkInfo
297+
Show-VSCodeSymlinkInfo
164298
}
165299
catch {
166300
$txtStatus.Text = "Symlink validation failed: $_"
@@ -171,26 +305,23 @@ function Start-VSCodeUpdaterGUI {
171305
# Start Safe Mode
172306
# -----------------------------
173307
$btnSafeMode.Add_Click({
174-
try {
175-
Start-VSCodeSafeMode
176-
$txtStatus.Text = "VS Code launched in Safe Mode."
177-
}
178-
catch {
179-
$txtStatus.Text = "Safe Mode launch failed: $_"
180-
}
308+
Start-VSCodeSafeMode
309+
})
310+
$chkSafeMode.Add_Checked({
311+
$script:SafeMode = $true
312+
_out "SAFE MODE ENABLED" "Yellow"
313+
})
314+
315+
$chkSafeMode.Add_Unchecked({
316+
$script:SafeMode = $false
317+
_out "SAFE MODE DISABLED" "Yellow"
181318
})
182319

183320
# -----------------------------
184321
# Open Dashboard
185322
# -----------------------------
186323
$btnDashboard.Add_Click({
187-
try {
188-
Get-VSCodeDashboard
189-
$txtStatus.Text = "Dashboard opened."
190-
}
191-
catch {
192-
$txtStatus.Text = "Dashboard failed to open: $_"
193-
}
324+
Show-DashboardInTerminal
194325
})
195326

196327
# -----------------------------
@@ -246,24 +377,106 @@ function Start-VSCodeUpdaterGUI {
246377

247378
$window.Add_Closed({
248379
$timer.Stop()
380+
$taskTimer.Stop()
381+
})
382+
$window.Add_Loaded({
383+
if ($chkSafeMode.IsChecked) {
384+
_out "SAFE MODE ENABLED" "Yellow"
385+
}
249386
})
250-
function Update-SymlinkInfo {
251-
$info = Get-VSCodeSymlinkInfo
252-
253-
$txtActiveVersion.Text = "Active Version: $($info.ActiveVersion)"
254-
$txtSymlinkTarget.Text = "Symlink Target: $($info.TargetPath)"
255-
$txtSymlinkValid.Text = "Symlink Status: " + ($info.IsValid ? "Valid" : "Broken")
256-
$txtLastUpdate.Text = "Last Update: $($info.LastUpdateResult)"
257-
$txtFallbackReason.Text = "Fallback Reason: $($info.LastFallbackReason)"
258-
}
259-
260-
# Helper: refresh version list
261-
function Update-VersionList {
262-
$dgVersions.ItemsSource = Get-VSCodeVersions
263-
}
264387

265388
# Show window
266389
$window.ShowDialog() | Out-Null
267390
}
391+
function Update-TaskViewer {
392+
param([string]$Text)
393+
394+
$window.Dispatcher.Invoke({
395+
$txtTaskViewer.AppendText("$Text`n")
396+
$txtTaskViewer.ScrollToEnd()
397+
})
398+
}
399+
function Update-TaskViewerStatus {
400+
$proc = Get-Process -Name "SetupApp" -ErrorAction SilentlyContinue
401+
402+
# Clear previous output
403+
$window.Dispatcher.Invoke({
404+
$txtTaskViewer.Document.Blocks.Clear()
405+
})
406+
407+
if ($proc) {
408+
Write-TaskViewerLine "SetupApp: Running (PID $($proc.Id))" "LightGreen"
409+
410+
# CPU is cumulative; WorkingSet64 is live memory
411+
Write-TaskViewerLine ("CPU Time: {0:N2} sec" -f $proc.CPU) "White"
412+
Write-TaskViewerLine ("Memory: {0:N2} MB" -f ($proc.WorkingSet64 / 1MB)) "White"
413+
414+
# Status classification
415+
if ($proc.WorkingSet64 -gt 50MB) {
416+
Write-TaskViewerLine "Status: Busy" "Yellow"
417+
}
418+
else {
419+
Write-TaskViewerLine "Status: Idle" "LightBlue"
420+
}
421+
}
422+
else {
423+
Write-TaskViewerLine "SetupApp: Not running" "Red"
424+
}
425+
426+
Write-TaskViewerLine ("Last check: {0}" -f (Get-Date -Format "HH:mm:ss")) "Gray"
427+
}
428+
function Update-Terminal {
429+
param([string]$Text)
430+
431+
$txtCommandOutput.AppendText($Text + "`n")
432+
$txtCommandOutput.CaretPosition = $txtCommandOutput.Document.ContentEnd
433+
$txtCommandOutput.ScrollToEnd()
434+
}
435+
function Update-SymlinkInfo {
436+
$info = Get-VSCodeSymlinkInfo
437+
438+
$txtActiveVersion.Text = "Active Version: $($info.ActiveVersion)"
439+
$txtSymlinkTarget.Text = "Symlink Target: $($info.TargetPath)"
440+
$txtSymlinkValid.Text = "Symlink Status: " + ($info.IsValid ? "Valid" : "Broken")
441+
$txtLastUpdate.Text = "Last Update: $($info.LastUpdateResult)"
442+
$txtFallbackReason.Text = "Fallback Reason: $($info.LastFallbackReason)"
443+
}
444+
445+
# Helper: refresh version list
446+
function Update-VersionList {
447+
$dgVersions.ItemsSource = Get-VSCodeVersions
448+
}
449+
function Write-Colored {
450+
param(
451+
[string]$Text,
452+
[string]$Color = "White"
453+
)
454+
455+
$run = New-Object System.Windows.Documents.Run
456+
$run.Text = $Text + "`n"
457+
$run.Foreground = $Color
458+
459+
$txtCommandOutput.Document.Blocks.Add($run)
460+
$txtCommandOutput.CaretPosition = $txtCommandOutput.Document.ContentEnd
461+
$txtCommandOutput.ScrollToEnd()
462+
}
463+
function Write-TaskViewerLine {
464+
param(
465+
[string]$Text,
466+
[string]$Color = "White"
467+
)
468+
469+
$window.Dispatcher.Invoke({
470+
$paragraph = New-Object System.Windows.Documents.Paragraph
471+
$run = New-Object System.Windows.Documents.Run
472+
473+
$run.Text = $Text
474+
$run.Foreground = $Color
475+
476+
$paragraph.Inlines.Add($run)
477+
$txtTaskViewer.Document.Blocks.Add($paragraph)
478+
$txtTaskViewer.ScrollToEnd()
479+
})
480+
}
268481

269482
Start-VSCodeUpdaterGUI

0 commit comments

Comments
 (0)