diff --git a/installer/PSLauncher.iss b/installer/PSLauncher.iss index a003d66..63655ff 100644 --- a/installer/PSLauncher.iss +++ b/installer/PSLauncher.iss @@ -11,7 +11,7 @@ #define MyAppName "PROSERVE Launcher" #define MyAppShortName "PS_Launcher" -#define MyAppVersion "1.0.6" +#define MyAppVersion "1.0.7" #define MyAppPublisher "ASTERION VR" #define MyAppURL "https://asterionvr.com" #define MyAppExeName "PS_Launcher.exe" diff --git a/src/PSLauncher.App/PSLauncher.App.csproj b/src/PSLauncher.App/PSLauncher.App.csproj index 20e5ecb..792e394 100644 --- a/src/PSLauncher.App/PSLauncher.App.csproj +++ b/src/PSLauncher.App/PSLauncher.App.csproj @@ -18,9 +18,9 @@ PROSERVE Launcher © 2026 ASTERION VR — All rights reserved PSLauncher.App - 1.0.6 - 1.0.6.0 - 1.0.6.0 + 1.0.7 + 1.0.7.0 + 1.0.7.0 true diff --git a/src/PSLauncher.App/ViewModels/MainViewModel.cs b/src/PSLauncher.App/ViewModels/MainViewModel.cs index 6644782..c6e7f61 100644 --- a/src/PSLauncher.App/ViewModels/MainViewModel.cs +++ b/src/PSLauncher.App/ViewModels/MainViewModel.cs @@ -763,7 +763,13 @@ public sealed partial class MainViewModel : ObservableObject // on garde le cache silencieusement (pas de crash). await RefreshLicenseFromServerAsync(CancellationToken.None); - var result = await _updateChecker.CheckAsync(CancellationToken.None); + // Passe canSeeBetas depuis la license courante — UpdateChecker exclut les + // betas de la sélection LatestRemote quand le client n'a pas les droits. + // Évite le popup « MAJ dispo : 1.5.4.32 beta » pour un client qui ne peut + // pas voir cette version dans la liste après filtrage RebuildList. + var result = await _updateChecker.CheckAsync( + _license?.CanSeeBetas ?? false, + CancellationToken.None); if (result.Error is not null) { StatusMessage = Strings.StatusError(result.Error); diff --git a/src/PSLauncher.Core/Updates/IUpdateChecker.cs b/src/PSLauncher.Core/Updates/IUpdateChecker.cs index d94dcbc..0042647 100644 --- a/src/PSLauncher.Core/Updates/IUpdateChecker.cs +++ b/src/PSLauncher.Core/Updates/IUpdateChecker.cs @@ -4,7 +4,14 @@ namespace PSLauncher.Core.Updates; public interface IUpdateChecker { - Task CheckAsync(CancellationToken ct); + /// + /// Si false, les versions marquées sont + /// exclues de la sélection du LatestRemote — pas de popup « MAJ dispo » + /// pour une beta que le client ne pourrait de toute façon pas voir dans la + /// liste après filtrage license côté MainViewModel.RebuildList. Le + /// manifest complet est quand même retourné pour le rendu ultérieur. + /// + Task CheckAsync(bool canSeeBetas, CancellationToken ct); } public sealed record UpdateCheckResult( diff --git a/src/PSLauncher.Core/Updates/UpdateChecker.cs b/src/PSLauncher.Core/Updates/UpdateChecker.cs index 87cfb52..14de0a6 100644 --- a/src/PSLauncher.Core/Updates/UpdateChecker.cs +++ b/src/PSLauncher.Core/Updates/UpdateChecker.cs @@ -21,7 +21,7 @@ public sealed class UpdateChecker : IUpdateChecker _logger = logger; } - public async Task CheckAsync(CancellationToken ct) + public async Task CheckAsync(bool canSeeBetas, CancellationToken ct) { try { @@ -32,8 +32,16 @@ public sealed class UpdateChecker : IUpdateChecker // ordonnant via VersionOrder — ça respecte la règle « non-beta > beta au // même préfixe 3-digit » (ex : 1.5.4 non-beta > 1.5.4.32 beta), sinon // c'est du SemVer strict. - var latest = manifest.Versions - .Where(v => v.AvailableForDownload) + // + // Filtre isBeta : les clients sans droits beta ne doivent JAMAIS voir une + // beta comme LatestRemote — sinon le popup « MAJ dispo » leur propose une + // version qu'ils ne pourront pas installer (filtrée en aval par RebuildList). + // Le filtre est appliqué avant le tri VersionOrder pour éviter qu'une beta + // ne se glisse comme "latest" chez un client non-autorisé, même si elle + // aurait été détrônée par une non-beta au même préfixe 3-digit. + var candidates = manifest.Versions.Where(v => v.AvailableForDownload); + if (!canSeeBetas) candidates = candidates.Where(v => !v.IsBeta); + var latest = candidates .OrderByDescending(v => v, Comparer.Create(VersionOrder.Compare)) .FirstOrDefault();