Skip to content

Commit

Permalink
feat(Vsix): Support for nuget icons
Browse files Browse the repository at this point in the history
  • Loading branch information
iadonkey committed Dec 7, 2024
1 parent 1224fc9 commit 611dbad
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 50 deletions.
57 changes: 35 additions & 22 deletions TwinpackCore/Protocol/Nuget/NugetServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,38 +150,51 @@ public virtual async Task<Tuple<IEnumerable<CatalogItemGetResponse>, bool>> GetC
#if !NETSTANDARD2_1_OR_GREATER
protected virtual async Task<System.Windows.Media.Imaging.BitmapImage> GetPackageIconAsync(PackageIdentity identity, CancellationToken cancellationToken)
{
FindPackageByIdResource resource = await _sourceRepository.GetResourceAsync<FindPackageByIdResource>();

using (MemoryStream packageStream = new MemoryStream())
try
{
await resource.CopyNupkgToStreamAsync(
identity.Id,
identity.Version,
packageStream,
_cache,
NullLogger.Instance,
cancellationToken);
FindPackageByIdResource resource = await _sourceRepository.GetResourceAsync<FindPackageByIdResource>();

using (PackageArchiveReader packageReader = new PackageArchiveReader(packageStream))
using (MemoryStream packageStream = new MemoryStream())
using (var memoryStream = new MemoryStream())
{
var iconPath = packageReader.NuspecReader.GetIcon();
if (iconPath != null)
await resource.CopyNupkgToStreamAsync(
identity.Id,
identity.Version,
packageStream,
_cache,
NullLogger.Instance,
cancellationToken);

using (PackageArchiveReader packageReader = new PackageArchiveReader(packageStream))
{
var zipEntry = packageReader.GetEntry(iconPath);
if (zipEntry != null)
var iconPath = packageReader.NuspecReader.GetIcon();
if (iconPath != null)
{
var image = new System.Windows.Media.Imaging.BitmapImage();
image.BeginInit();
image.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad;
image.StreamSource = zipEntry.Open();
image.EndInit();
image.Freeze();
return image;
var zipEntry = packageReader.GetEntry(iconPath);

await zipEntry.Open().CopyToAsync(memoryStream);
memoryStream.Position = 0;

if (zipEntry != null)
{
var image = new System.Windows.Media.Imaging.BitmapImage();
image.BeginInit();
image.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad;
image.StreamSource = memoryStream;
image.EndInit();
image.Freeze();
return image;
}
}
}
}
} catch (Exception ex)
{
_logger.Trace(ex);
_logger.Error("Can't unpack package icon:" + ex);
}


return null;
}
#endif
Expand Down
23 changes: 11 additions & 12 deletions TwinpackVsixShared/Dialogs/CatalogWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
<local:IntToVisibilityConverter x:Key="IntToVisibilityConverter"/>
<local:BooleanToBorderThicknessConverter x:Key="BooleanToBorderThicknessConverter"/>
<local:VersionToStringConverter x:Key="VersionToStringConverter"/>
<local:CatalogIconUrlVisibilityConverter x:Key="CatalogIconUrlVisibilityConverter"/>
<local:CatalogIconVisibilityConverter x:Key="CatalogIconVisibilityConverter"/>
<local:CatalogNoIconVisibilityConverter x:Key="CatalogNoIconVisibilityConverter"/>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
Expand Down Expand Up @@ -142,23 +145,19 @@
<ColumnDefinition Width="auto"></ColumnDefinition>
</Grid.ColumnDefinitions>

<Image d:Source="Images/Twinpack.png"
RenderOptions.BitmapScalingMode="HighQuality"
x:Name="ImageIcon"
<Image RenderOptions.BitmapScalingMode="HighQuality"
DataContext="{Binding Catalog}"
Visibility="{Binding IconUrl, Converter={StaticResource NullToVisibilityConverter}}"
Visibility="{Binding ., Converter={StaticResource CatalogIconUrlVisibilityConverter}}"
Source="{Binding IconUrl, Converter={StaticResource UrlToImageConverter}}" VerticalAlignment="Top" Grid.Column="0" Width="48" Height="48"/>

<Image d:Source="Images/Twinpack.png"
RenderOptions.BitmapScalingMode="HighQuality"
<Image RenderOptions.BitmapScalingMode="HighQuality"
DataContext="{Binding Catalog}"
Visibility="{Binding Icon, Converter={StaticResource NullToVisibilityConverter}}"
Source="{Binding Icon}" VerticalAlignment="Top" Grid.Column="0" Width="48" Height="48"/>

<Image d:Source="Images/Twinpack.png"
RenderOptions.BitmapScalingMode="HighQuality"
Visibility="{Binding ., Converter={StaticResource CatalogIconVisibilityConverter}}"
Source="{Binding Icon}" VerticalAlignment="Top" Grid.Column="0" Width="48" Height="48"/>

<Image RenderOptions.BitmapScalingMode="HighQuality"
DataContext="{Binding Catalog}"
Visibility="{Binding Visibility, ElementName=ImageIcon, Converter={StaticResource VisibilityToInverseVisibilityConverter}}"
Visibility="{Binding ., Converter={StaticResource CatalogNoIconVisibilityConverter}}"
Source="{Binding Name, Converter={StaticResource UrlToImageConverter}}" VerticalAlignment="Top" Grid.Column="0" Width="48" Height="48"/>

<Grid Grid.Column="1" DataContext="{Binding Catalog}">
Expand Down
4 changes: 0 additions & 4 deletions TwinpackVsixShared/Dialogs/CatalogWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ public partial class CatalogWindow : UserControl, INotifyPropertyChanged
private const int _itemsPerPage = 10;

private bool _isUpdateAvailable = false;
private bool _isLoadingConfig = false;
private bool _isPackageVersionsAvailable = false;

private string _searchTerm = "";
Expand Down Expand Up @@ -479,7 +478,6 @@ public async Task<Config> LoadConfigAsync(string plcName, CancellationToken canc
{
if (plcName == null)
{
_isLoadingConfig = false;
IsCreateConfigVisible = false;
IsMigrateConfigVisible = false;
IsConfigured = false;
Expand All @@ -488,7 +486,6 @@ public async Task<Config> LoadConfigAsync(string plcName, CancellationToken canc

try
{
_isLoadingConfig = true;
await Microsoft.VisualStudio.Shell.ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

var config = ConfigFactory.Load(Path.GetDirectoryName(_context.Solution.FullName));
Expand Down Expand Up @@ -517,7 +514,6 @@ public async Task<Config> LoadConfigAsync(string plcName, CancellationToken canc
}
finally
{
_isLoadingConfig = false;
}

return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.Windows.Data;
using System.Windows;
using System.Globalization;
using Twinpack.Protocol.Api;

namespace Twinpack.Dialogs
{
public class CatalogIconUrlVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return Visibility.Collapsed;

if (value is CatalogItemGetResponse catalogItem)
{
return catalogItem.Icon == null && catalogItem.IconUrl != null ? Visibility.Visible : Visibility.Collapsed;
}

return Visibility.Collapsed;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.Windows.Data;
using System.Windows;
using System.Globalization;
using Twinpack.Protocol.Api;

namespace Twinpack.Dialogs
{
public class CatalogIconVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return Visibility.Collapsed;

if (value is CatalogItemGetResponse catalogItem)
{
return catalogItem.Icon == null ? Visibility.Collapsed : Visibility.Visible;
}

return Visibility.Collapsed;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.Windows.Data;
using System.Windows;
using System.Globalization;
using Twinpack.Protocol.Api;

namespace Twinpack.Dialogs
{
public class CatalogNoIconVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return Visibility.Collapsed;

if (value is CatalogItemGetResponse catalogItem)
{
return catalogItem.IconUrl == null && catalogItem.Icon == null ? Visibility.Visible : Visibility.Collapsed;
}

return Visibility.Collapsed;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class UrlToImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return IconCache.Icon((string)value, parameter != null && (parameter as string).Contains("Beckhoff"));
return IconCache.Icon((string)value);
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
Expand Down
6 changes: 3 additions & 3 deletions TwinpackVsixShared/Dialogs/PackageVersionWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ private async void Window_Loaded(object sender, RoutedEventArgs e)
Version = _packageVersion?.Version ?? _plcConfig?.Version;
Authors = _packageVersion?.Authors ?? _plcConfig?.Authors;
License = _packageVersion?.License ?? _plcConfig?.License;
IconImage = IconCache.Icon(_package?.IconUrl ?? PackageName, isBeckhoffPackage: false);
IconImage = IconCache.Icon(_package?.IconUrl ?? PackageName);
Notes = _packageVersion?.Notes;
Version = _packageVersion?.Version;
LatestVersion = _packageVersionLatest?.Version;
Expand Down Expand Up @@ -750,7 +750,7 @@ private void ChangeIcon_Click(object sender, RoutedEventArgs e)
if (openFileDialog.ShowDialog() == true)
{
IconFile = openFileDialog.FileName;
IconImage = IconCache.Icon(openFileDialog.FileName, isBeckhoffPackage: false);
IconImage = IconCache.Icon(openFileDialog.FileName);
}
}
catch (Exception ex)
Expand Down Expand Up @@ -790,7 +790,7 @@ private async Task<bool> PatchPackageAsync(CancellationToken cancellationToken)
ProjectUrl = packageResult.ProjectUrl;
Authors = packageResult.Authors;
License = packageResult.License;
IconImage = IconCache.Icon(packageResult?.IconUrl ?? PackageName, isBeckhoffPackage: false);
IconImage = IconCache.Icon(packageResult?.IconUrl ?? PackageName);
}
catch (Exceptions.ProtocolException ex)
{
Expand Down
16 changes: 8 additions & 8 deletions TwinpackVsixShared/IconCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ public class IconCache
{
private static Dictionary<string, BitmapImage> _icons;

public static byte[] GenerateIdenticon(string packageName, bool isBeckhoffPackage)
public static byte[] GenerateIdenticon(string packageName)
{
var size = 128;
var renderer = new PngRenderer(size, size);
var icon = Jdenticon.Identicon.FromValue(packageName, size);

icon.Style = new Jdenticon.IdenticonStyle
{
Hues = isBeckhoffPackage ? new HueCollection { { 0, HueUnit.Degrees } } : new HueCollection { { 216, HueUnit.Degrees } },
Hues = new HueCollection { { 216, HueUnit.Degrees } },
BackColor = Color.Transparent,
ColorLightness = Jdenticon.Range.Create(0.37f, 0.37f),
GrayscaleLightness = isBeckhoffPackage ? Jdenticon.Range.Create(0.435f, 0.435f) : Jdenticon.Range.Create(0.37f, 0.37f),
ColorSaturation = isBeckhoffPackage ? 1.00f : 0.26f,
GrayscaleLightness = Jdenticon.Range.Create(0.37f, 0.37f),
ColorSaturation = 0.26f,
GrayscaleSaturation = 0.26f
};

Expand All @@ -35,11 +35,11 @@ public static byte[] GenerateIdenticon(string packageName, bool isBeckhoffPackag
}
}

public static BitmapImage GenerateIdenticonAsBitmapImage(string packageName, bool isBeckhoffPackage)
public static BitmapImage GenerateIdenticonAsBitmapImage(string packageName)
{
var image = new BitmapImage();

using (var stream = new MemoryStream(GenerateIdenticon(packageName, isBeckhoffPackage)))
using (var stream = new MemoryStream(GenerateIdenticon(packageName)))
{
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
Expand All @@ -51,14 +51,14 @@ public static BitmapImage GenerateIdenticonAsBitmapImage(string packageName, boo
return image;
}

public static BitmapImage Icon(string iconUrl, bool isBeckhoffPackage)
public static BitmapImage Icon(string iconUrl)
{
if (_icons == null)
_icons = new Dictionary<string, BitmapImage>();

if (iconUrl?.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase) == false)
{
var img = GenerateIdenticonAsBitmapImage(iconUrl, isBeckhoffPackage);
var img = GenerateIdenticonAsBitmapImage(iconUrl);
return img;
}

Expand Down
3 changes: 3 additions & 0 deletions TwinpackVsixShared/TwinpackVsixShared.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
<Compile Include="$(MSBuildThisFileDirectory)Dialogs\Converters\BooleanToInverseBooleanConverter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Dialogs\Converters\BooleanToBorderThicknessConverter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Dialogs\Converters\BooleanToVisibilityConverter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Dialogs\Converters\CatalogIconUrlVisibilityConverter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Dialogs\Converters\CatalogNoIconVisibilityConverter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Dialogs\Converters\IntToVisibilityConverter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Dialogs\Converters\CatalogIconVisibilityConverter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Dialogs\Converters\NullToVisibilityConverter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Dialogs\Converters\UrlToImageConverter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Dialogs\Converters\VersionToStringConverter.cs" />
Expand Down

0 comments on commit 611dbad

Please sign in to comment.