Skip to content

Commit 2a04c85

Browse files
committed
feat: add channel type badge to VS instance list
Display build channel (Stable, Preview, Canary, Internal Preview) as a colored badge next to each Visual Studio installation. Color-coded badges provide quick visual identification of the installation channel.
1 parent 20272cb commit 2a04c85

File tree

5 files changed

+70
-18
lines changed

5 files changed

+70
-18
lines changed

src/CodingWithCalvin.VSToolbox.Core/Models/LaunchableInstance.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public sealed class LaunchableInstance
1515
public string BuildNumber => Instance.BuildNumber;
1616
public string InstallationPath => Instance.InstallationPath;
1717
public bool IsPrerelease => Instance.IsPrerelease;
18+
public string ChannelType => Instance.ChannelType;
1819
public string? IconPath => Instance.IconPath;
1920
public bool CanLaunch => Instance.CanLaunch;
2021

src/CodingWithCalvin.VSToolbox.Core/Models/VisualStudioInstance.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,26 @@ public sealed class VisualStudioInstance
2121

2222
public string BuildNumber => InstallationVersion;
2323

24+
public string ChannelType => ParseChannelType(ChannelId);
25+
26+
private static string ParseChannelType(string channelId)
27+
{
28+
// ChannelId format: VisualStudio.{majorVersion}.{channel}
29+
// e.g., VisualStudio.17.Release, VisualStudio.17.Preview, VisualStudio.17.Canary
30+
var parts = channelId.Split('.');
31+
if (parts.Length < 3)
32+
return "Unknown";
33+
34+
return parts[^1] switch
35+
{
36+
"Release" => "Stable",
37+
"Preview" => "Preview",
38+
"Canary" => "Canary",
39+
"IntPreview" => "Internal Preview",
40+
_ => parts[^1]
41+
};
42+
}
43+
2444
public bool CanLaunch => !string.IsNullOrEmpty(ProductPath) &&
2545
ProductPath.EndsWith("devenv.exe", StringComparison.OrdinalIgnoreCase);
2646

src/CodingWithCalvin.VSToolbox/App.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<converters:FilePathToImageConverter x:Key="FilePathToImageConverter"/>
2020
<converters:CountToVisibilityConverter x:Key="CountToVisibilityConverter"/>
2121
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
22+
<converters:ChannelTypeToBrushConverter x:Key="ChannelTypeToBrushConverter"/>
2223

2324
<x:Double x:Key="AppFontSize">14</x:Double>
2425

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using Microsoft.UI;
2+
using Microsoft.UI.Xaml.Data;
3+
using Microsoft.UI.Xaml.Media;
4+
5+
namespace CodingWithCalvin.VSToolbox.Converters;
6+
7+
public sealed class ChannelTypeToBrushConverter : IValueConverter
8+
{
9+
public object Convert(object? value, Type targetType, object? parameter, string language)
10+
{
11+
var channelType = value as string ?? "Unknown";
12+
13+
return channelType switch
14+
{
15+
"Stable" => new SolidColorBrush(ColorHelper.FromArgb(255, 34, 197, 94)), // Green
16+
"Preview" => new SolidColorBrush(ColorHelper.FromArgb(255, 168, 85, 247)), // Purple
17+
"Canary" => new SolidColorBrush(ColorHelper.FromArgb(255, 251, 191, 36)), // Amber/Yellow
18+
"Internal Preview" => new SolidColorBrush(ColorHelper.FromArgb(255, 239, 68, 68)), // Red
19+
_ => new SolidColorBrush(ColorHelper.FromArgb(255, 107, 114, 128)) // Gray
20+
};
21+
}
22+
23+
public object ConvertBack(object? value, Type targetType, object? parameter, string language)
24+
{
25+
throw new NotImplementedException();
26+
}
27+
}

src/CodingWithCalvin.VSToolbox/Views/MainPage.xaml

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -84,34 +84,37 @@
8484
TextTrimming="CharacterEllipsis"/>
8585
</StackPanel>
8686

87-
<!-- Prerelease Badge -->
87+
<!-- Channel Type Badge -->
8888
<Border
8989
Grid.Column="2"
90-
Visibility="{x:Bind IsPrerelease}"
91-
Background="{ThemeResource SystemAccentColorDark1}"
9290
CornerRadius="4"
9391
Padding="8,4"
94-
VerticalAlignment="Center">
92+
VerticalAlignment="Center"
93+
Background="{x:Bind ChannelType, Converter={StaticResource ChannelTypeToBrushConverter}}">
9594
<TextBlock
96-
Text="Preview"
95+
Text="{x:Bind ChannelType}"
9796
FontSize="10"
98-
Foreground="{ThemeResource TextOnAccentFillColorPrimaryBrush}"/>
97+
FontWeight="SemiBold"
98+
Foreground="White"/>
9999
</Border>
100100

101101
<!-- Action Buttons -->
102102
<StackPanel Grid.Column="3" Orientation="Horizontal" Spacing="4" VerticalAlignment="Center">
103-
<Button
104-
Click="OnLaunchClick"
105-
ToolTipService.ToolTip="Launch"
106-
Visibility="{x:Bind CanLaunch, Converter={StaticResource BoolToVisibilityConverter}}"
107-
Padding="8"
108-
Background="Transparent"
109-
BorderThickness="0"
110-
Opacity="0.6"
111-
PointerEntered="OnButtonPointerEntered"
112-
PointerExited="OnButtonPointerExited">
113-
<SymbolIcon Symbol="Play" Foreground="#22C55E"/>
114-
</Button>
103+
<!-- Fixed-width container to maintain alignment when Play button is hidden -->
104+
<Border Width="40">
105+
<Button
106+
Click="OnLaunchClick"
107+
ToolTipService.ToolTip="Launch"
108+
Visibility="{x:Bind CanLaunch, Converter={StaticResource BoolToVisibilityConverter}}"
109+
Padding="8"
110+
Background="Transparent"
111+
BorderThickness="0"
112+
Opacity="0.6"
113+
PointerEntered="OnButtonPointerEntered"
114+
PointerExited="OnButtonPointerExited">
115+
<SymbolIcon Symbol="Play" Foreground="#22C55E"/>
116+
</Button>
117+
</Border>
115118
<Button
116119
ToolTipService.ToolTip="Options"
117120
Padding="8"

0 commit comments

Comments
 (0)