diff --git a/Dashboard/AboutWindow.xaml.cs b/Dashboard/AboutWindow.xaml.cs index 0e61086e..576820f3 100644 --- a/Dashboard/AboutWindow.xaml.cs +++ b/Dashboard/AboutWindow.xaml.cs @@ -8,6 +8,8 @@ using System.Reflection; using System.Windows; using PerformanceMonitorDashboard.Services; +using Velopack; +using System; namespace PerformanceMonitorDashboard { @@ -19,6 +21,8 @@ public partial class AboutWindow : Window private const string DarlingDataUrl = "https://www.erikdarling.com"; private string? _updateReleaseUrl; + private UpdateManager? _velopackMgr; + private Velopack.UpdateInfo? _pendingUpdate; public AboutWindow() { @@ -47,6 +51,32 @@ private async void CheckUpdatesLink_Click(object sender, RoutedEventArgs e) UpdateStatusText.Text = "Checking for updates..."; UpdateStatusText.Visibility = Visibility.Visible; + // Try Velopack first (supports download + apply) + try + { + _velopackMgr = new UpdateManager( + new Velopack.Sources.GithubSource("https://github.com/erikdarlingdata/PerformanceMonitor", null, false)); + + var updateInfo = await _velopackMgr.CheckForUpdatesAsync(); + if (updateInfo != null) + { + _pendingUpdate = updateInfo; + UpdateStatusText.Text = $"Update available: v{updateInfo.TargetFullRelease.Version} — click to download and install"; + UpdateStatusText.Cursor = System.Windows.Input.Cursors.Hand; + UpdateStatusText.MouseLeftButtonUp -= UpdateStatusText_Click; + UpdateStatusText.MouseLeftButtonUp += VelopackDownload_Click; + UpdateStatusText.TextDecorations = System.Windows.TextDecorations.Underline; + UpdateStatusText.Foreground = FindResource("AccentBrush") as System.Windows.Media.Brush + ?? System.Windows.Media.Brushes.DodgerBlue; + return; + } + } + catch + { + // Velopack packages may not exist yet — fall through to legacy check + } + + // Fallback: GitHub Releases API check (opens browser) var result = await UpdateCheckService.CheckForUpdateAsync(bypassCache: true); if (result == null) @@ -56,8 +86,9 @@ private async void CheckUpdatesLink_Click(object sender, RoutedEventArgs e) else if (result.IsUpdateAvailable) { _updateReleaseUrl = result.ReleaseUrl; - UpdateStatusText.Text = $"Update available: {result.LatestVersion} (you have {result.CurrentVersion})"; + UpdateStatusText.Text = $"Update available: {result.LatestVersion} (you have {result.CurrentVersion}) — click to open releases"; UpdateStatusText.Cursor = System.Windows.Input.Cursors.Hand; + UpdateStatusText.MouseLeftButtonUp -= VelopackDownload_Click; UpdateStatusText.MouseLeftButtonUp += UpdateStatusText_Click; UpdateStatusText.TextDecorations = System.Windows.TextDecorations.Underline; UpdateStatusText.Foreground = FindResource("AccentBrush") as System.Windows.Media.Brush @@ -69,6 +100,33 @@ private async void CheckUpdatesLink_Click(object sender, RoutedEventArgs e) } } + private async void VelopackDownload_Click(object sender, System.Windows.Input.MouseButtonEventArgs e) + { + if (_velopackMgr == null || _pendingUpdate == null) return; + + try + { + UpdateStatusText.MouseLeftButtonUp -= VelopackDownload_Click; + UpdateStatusText.TextDecorations = null; + UpdateStatusText.Cursor = System.Windows.Input.Cursors.Arrow; + UpdateStatusText.Text = "Downloading update..."; + + await _velopackMgr.DownloadUpdatesAsync(_pendingUpdate); + + UpdateStatusText.Text = "Update downloaded. Click to restart and apply."; + UpdateStatusText.Cursor = System.Windows.Input.Cursors.Hand; + UpdateStatusText.TextDecorations = System.Windows.TextDecorations.Underline; + UpdateStatusText.MouseLeftButtonUp += (_, _) => + { + _velopackMgr.ApplyUpdatesAndRestart(_pendingUpdate.TargetFullRelease); + }; + } + catch (Exception ex) + { + UpdateStatusText.Text = $"Download failed: {ex.Message}"; + } + } + private void UpdateStatusText_Click(object sender, System.Windows.Input.MouseButtonEventArgs e) { if (!string.IsNullOrEmpty(_updateReleaseUrl)) diff --git a/Dashboard/MainWindow.xaml.cs b/Dashboard/MainWindow.xaml.cs index 8d67436b..33f493a8 100644 --- a/Dashboard/MainWindow.xaml.cs +++ b/Dashboard/MainWindow.xaml.cs @@ -179,6 +179,29 @@ private async Task CheckForUpdatesOnStartupAsync() var prefs = _preferencesService.GetPreferences(); if (!prefs.CheckForUpdatesOnStartup) return; + // Try Velopack first (supports download + apply) + try + { + var mgr = new Velopack.UpdateManager( + new Velopack.Sources.GithubSource( + "https://github.com/erikdarlingdata/PerformanceMonitor", null, false)); + + var newVersion = await mgr.CheckForUpdatesAsync(); + if (newVersion != null) + { + _notificationService?.ShowNotification( + "Update Available", + $"Performance Monitor {newVersion.TargetFullRelease.Version} is available. Use Help > About to download and install.", + NotificationType.Info); + return; + } + } + catch + { + // Velopack packages may not exist yet — fall through to legacy check + } + + // Fallback: GitHub Releases API check (notification only) var result = await UpdateCheckService.CheckForUpdateAsync(); if (result?.IsUpdateAvailable == true) {