From 973a1e78ba3622f7381c999eda2dd67bdb879034 Mon Sep 17 00:00:00 2001 From: "j.foucher" Date: Sat, 2 May 2026 08:50:10 +0200 Subject: [PATCH] UI: license summary becomes a colored badge in the top bar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The license info was rendered as plain secondary-grey text, easy to miss. Now it's a rounded pill (CornerRadius=14) with traffic-light colors driven by the new MainViewModel.LicenseSeverity property: - Ok → green pill (Brush.Status.Installed) with ✓ icon - Warning → amber pill (Brush.Status.Busy) with ⏰ icon, fires when entitlement is < 30 days away from expiry - Error → red pill (#EF4444 / #2A1414 bg) with 🔒/⚠/🚫 icon depending on whether license is missing, expired, revoked Two new VM properties accompany LicenseSummary: - LicenseIcon: emoji glyph for the pill - LicenseSeverity: enum-like string Ok/Warning/Error driving DataTriggers Both are kept in sync via NotifyLicenseChanged(), called wherever _license used to trigger only OnPropertyChanged(LicenseSummary). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../ViewModels/MainViewModel.cs | 65 ++++++++++++++++-- src/PSLauncher.App/Views/MainWindow.xaml | 66 ++++++++++++++++++- 2 files changed, 122 insertions(+), 9 deletions(-) diff --git a/src/PSLauncher.App/ViewModels/MainViewModel.cs b/src/PSLauncher.App/ViewModels/MainViewModel.cs index 5582cf2..425fbb6 100644 --- a/src/PSLauncher.App/ViewModels/MainViewModel.cs +++ b/src/PSLauncher.App/ViewModels/MainViewModel.cs @@ -69,15 +69,68 @@ public sealed partial class MainViewModel : ObservableObject { get { - if (_license is null) return "License : non configurée"; + if (_license is null) return "Aucune license"; if (_license.Status == "valid") - return $"License : {_license.OwnerName} • exp. {_license.DownloadEntitlementUntil:dd/MM/yyyy}"; + { + var until = _license.DownloadEntitlementUntil; + if (until is { } u && (u - DateTime.UtcNow).TotalDays < 30) + return $"{_license.OwnerName} • exp. {u:dd/MM/yyyy}"; + return $"{_license.OwnerName} • exp. {until:dd/MM/yyyy}"; + } if (_license.Status == "expired") - return $"License expirée le {_license.DownloadEntitlementUntil:dd/MM/yyyy}"; - return $"License : {_license.Status}"; + return $"Expirée le {_license.DownloadEntitlementUntil:dd/MM/yyyy}"; + if (_license.Status == "revoked") + return "Révoquée"; + return _license.Status; } } + public string LicenseIcon + { + get + { + if (_license is null) return "🔒"; + return _license.Status switch + { + "valid" when IsLicenseExpiringSoon() => "⏰", + "valid" => "✓", + "expired" => "⚠", + "revoked" => "🚫", + _ => "❓", + }; + } + } + + /// + /// Catégorie utilisée par la UI pour piloter la couleur du badge license. + /// + public string LicenseSeverity + { + get + { + if (_license is null) return "Error"; + return _license.Status switch + { + "valid" when IsLicenseExpiringSoon() => "Warning", + "valid" => "Ok", + _ => "Error", + }; + } + } + + private bool IsLicenseExpiringSoon() + { + if (_license?.DownloadEntitlementUntil is not { } until) return false; + return (until - DateTime.UtcNow).TotalDays < 30; + } + + private void NotifyLicenseChanged() + { + OnPropertyChanged(nameof(LicenseSummary)); + OnPropertyChanged(nameof(LicenseIcon)); + OnPropertyChanged(nameof(LicenseSeverity)); + } + public string EmptyHint => "Aucune version locale ni distante.\n" + "Clique « Vérifier les mises à jour » pour récupérer le catalogue depuis le serveur, " + @@ -257,7 +310,7 @@ public sealed partial class MainViewModel : ObservableObject { // Au retour, l'URL serveur ou l'installRoot ont pu changer → refresh _license = _licenseService.GetCached(); - OnPropertyChanged(nameof(LicenseSummary)); + NotifyLicenseChanged(); RebuildList(); } } @@ -270,7 +323,7 @@ public sealed partial class MainViewModel : ObservableObject if (dialog.LicenseActivated) { _license = _licenseService.GetCached(); - OnPropertyChanged(nameof(LicenseSummary)); + NotifyLicenseChanged(); RebuildList(); } await Task.CompletedTask; diff --git a/src/PSLauncher.App/Views/MainWindow.xaml b/src/PSLauncher.App/Views/MainWindow.xaml index 4813ff5..de95954 100644 --- a/src/PSLauncher.App/Views/MainWindow.xaml +++ b/src/PSLauncher.App/Views/MainWindow.xaml @@ -170,9 +170,69 @@ Content="📁 Dossier" Command="{Binding OpenInstallRootCommand}" Margin="0,0,12,0" /> - + + + + + + + + + + + + + + + + + +