diff --git a/installer/PSLauncher.iss b/installer/PSLauncher.iss
index 0d009a1..3a12834 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.8"
+#define MyAppVersion "1.0.9"
#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 2509a8d..1b1604a 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.8
- 1.0.8.0
- 1.0.8.0
+ 1.0.9
+ 1.0.9.0
+ 1.0.9.0
true
diff --git a/src/PSLauncher.App/ViewModels/MainViewModel.cs b/src/PSLauncher.App/ViewModels/MainViewModel.cs
index 3ef645f..30874bb 100644
--- a/src/PSLauncher.App/ViewModels/MainViewModel.cs
+++ b/src/PSLauncher.App/ViewModels/MainViewModel.cs
@@ -657,6 +657,15 @@ public sealed partial class MainViewModel : ObservableObject
}
}
+ // Marque les rows qui partagent un numéro de version avec au moins UNE
+ // autre row visible → active leur badge channel (sinon caché pour ne pas
+ // polluer l'UI mono-channel). Group by Version, count >= 2 → conflict.
+ foreach (var grp in rows.GroupBy(r => r.Version, StringComparer.OrdinalIgnoreCase))
+ {
+ bool hasConflict = grp.Count() >= 2;
+ foreach (var r in grp) r.HasVersionConflict = hasConflict;
+ }
+
// Featured : plus haute installée, sinon plus haute distante
var featured = rows.FirstOrDefault(r => r.IsInstalled) ?? rows.FirstOrDefault();
FeaturedVersion = featured;
diff --git a/src/PSLauncher.App/ViewModels/VersionRowViewModel.cs b/src/PSLauncher.App/ViewModels/VersionRowViewModel.cs
index 216b790..1418ae9 100644
--- a/src/PSLauncher.App/ViewModels/VersionRowViewModel.cs
+++ b/src/PSLauncher.App/ViewModels/VersionRowViewModel.cs
@@ -56,7 +56,24 @@ public sealed partial class VersionRowViewModel : ObservableObject
.FirstOrDefault(c => !string.IsNullOrWhiteSpace(c)
&& !string.Equals(c, "default", StringComparison.OrdinalIgnoreCase));
- public bool HasChannelBadge => !string.IsNullOrEmpty(ChannelBadge);
+ ///
+ /// True si au moins une AUTRE row visible sur ce launcher partage le même
+ /// numéro de version. Positionné par MainViewModel.RebuildList après
+ /// construction des rows (group by Version, count >= 2 → conflict).
+ /// Le badge channel n'est utile QUE dans ce cas — sinon la row est
+ /// univoque et le badge ajoute du bruit visuel.
+ ///
+ [ObservableProperty]
+ [NotifyPropertyChangedFor(nameof(HasChannelBadge))]
+ private bool _hasVersionConflict;
+
+ ///
+ /// Le badge n'est visible QUE quand la row a un channel spécifique ET qu'une
+ /// autre row visible partage le même numéro de version. Ça garde l'UI propre
+ /// sur les setups mono-channel (99 % des cas) et affiche le distingueur
+ /// seulement quand il est réellement nécessaire.
+ ///
+ public bool HasChannelBadge => !string.IsNullOrEmpty(ChannelBadge) && HasVersionConflict;
///
/// True si la version est taggée BÊTA dans le manifest (champ