Right sidebar nav: Library / Reports / Documentation tabs (WebView2)

The body of the launcher is now a 2-column layout:
- Left : swappable content area
- Right (200px) : sidebar with 3 nav buttons + active-state highlighting

Three pages, all under the same window chrome / footer:

1. **Library** (default) — the existing main view (featured version,
   other versions list, floating "Vérifier les MAJ" button, copyright).
2. **Reports** — embedded WebView2 navigated to a configurable URL.
   Default http://localhost/ProserveReport/ which matches the local
   stats tool installed on each customer machine alongside XAMPP.
3. **Documentation** — WebView2 with a configurable URL, falls back
   to a placeholder explaining where to set it if empty.

Implementation
- LocalConfig gains ReportUrl + DocumentationUrl (string).
- MainViewModel gains LauncherPage enum + CurrentPage state with
  Navigate{Library,Report,Documentation}Command. ReportUri /
  DocumentationUri parse the strings to Uri for WebView2.Source.
- Theme.xaml: NavButton style (transparent, left-aligned, hover
  darken, active state highlighted via Tag bool + accent left-border).
- InverseBoolToVisibilityConverter added (true → Collapsed) for the
  documentation placeholder fallback.
- Microsoft.Web.WebView2 NuGet (1.0.2792.45). Runtime is pre-installed
  on Win11 and auto-pushed via Windows Update on Win10. If absent,
  WebView2 surfaces an error which the user sees inline.
- Settings → Avancés → Serveur extended with the two URL fields.
- Strings.cs: NavLibrary / NavReport / NavDocumentation,
  SettingsReportUrl / SettingsDocsUrl, DocsPlaceholder, WebViewLoadError.
  Sidebar localized in 5 languages.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-03 08:52:51 +02:00
parent f62b212fc1
commit 288cad585a
9 changed files with 237 additions and 1 deletions

View File

@@ -21,6 +21,12 @@ using PSLauncher.Models;
namespace PSLauncher.App.ViewModels;
/// <summary>
/// Onglets affichés dans la sidebar droite du launcher. Chacun correspond à un
/// bloc de contenu visible/caché dans la fenêtre principale.
/// </summary>
public enum LauncherPage { Library, Report, Documentation }
public sealed partial class MainViewModel : ObservableObject
{
private readonly IInstallationRegistry _registry;
@@ -68,6 +74,34 @@ public sealed partial class MainViewModel : ObservableObject
[ObservableProperty] private double _progressPercent;
/// <summary>
/// Onglet actuellement actif dans la sidebar droite. La UI montre le bon bloc
/// via les converters IsLibrary / IsReport / IsDocumentation. Default = Library
/// pour que le launcher s'ouvre directement sur l'écran principal.
/// </summary>
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(IsLibrary))]
[NotifyPropertyChangedFor(nameof(IsReport))]
[NotifyPropertyChangedFor(nameof(IsDocumentation))]
private LauncherPage _currentPage = LauncherPage.Library;
public bool IsLibrary => CurrentPage == LauncherPage.Library;
public bool IsReport => CurrentPage == LauncherPage.Report;
public bool IsDocumentation => CurrentPage == LauncherPage.Documentation;
/// <summary>URL résolue pour le panneau Reports. WebView2.Source attend un Uri.</summary>
public Uri? ReportUri => TryParseUri(_config.ReportUrl);
/// <summary>URL résolue pour le panneau Documentation. Null si non configurée.</summary>
public Uri? DocumentationUri => TryParseUri(_config.DocumentationUrl);
public bool HasDocumentationUrl => DocumentationUri is not null;
private static Uri? TryParseUri(string? s)
=> !string.IsNullOrWhiteSpace(s) && Uri.TryCreate(s, UriKind.Absolute, out var u) ? u : null;
[RelayCommand] private void NavigateLibrary() => CurrentPage = LauncherPage.Library;
[RelayCommand] private void NavigateReport() => CurrentPage = LauncherPage.Report;
[RelayCommand] private void NavigateDocumentation() => CurrentPage = LauncherPage.Documentation;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(FooterText))]
[NotifyPropertyChangedFor(nameof(FooterVisibility))]