Skip to content

Commit 90b34b4

Browse files
committed
Feature to display unsupported extensions
1 parent d1c0a4d commit 90b34b4

File tree

12 files changed

+92
-27
lines changed

12 files changed

+92
-27
lines changed

src/ExtensionManager.UI/DialogService.cs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System.Runtime.Remoting.Channels;
2+
13
using ExtensionManager.Manifest;
24
using ExtensionManager.UI.Utils;
35
using ExtensionManager.UI.ViewModels;
@@ -61,19 +63,33 @@ private async Task ShowExportDialogAsync(IExportWorker worker, IManifest manifes
6163
await ShowInstallExportDialogAsync(vm);
6264
}
6365

64-
public Task ShowInstallDialogAsync(IInstallWorker worker, IManifest manifest, IReadOnlyCollection<IVSExtension> installedExtensions)
65-
=> ShowInstallForSolutionDialogAsync(worker, manifest, installedExtensions, forSolution: false);
66-
public Task ShowInstallForSolutionDialogAsync(IInstallWorker worker, IManifest manifest, IReadOnlyCollection<IVSExtension> installedExtensions)
67-
=> ShowInstallForSolutionDialogAsync(worker, manifest, installedExtensions, forSolution: true);
68-
private async Task ShowInstallForSolutionDialogAsync(IInstallWorker worker, IManifest manifest, IReadOnlyCollection<IVSExtension> installedExtensions, bool forSolution)
66+
public Task ShowInstallDialogAsync(IInstallWorker worker, IManifest manifest, IReadOnlyCollection<VSExtensionToInstall> extensions)
67+
=> ShowInstallForSolutionDialogAsync(worker, manifest, extensions, forSolution: false);
68+
public Task ShowInstallForSolutionDialogAsync(IInstallWorker worker, IManifest manifest, IReadOnlyCollection<VSExtensionToInstall> extensions)
69+
=> ShowInstallForSolutionDialogAsync(worker, manifest, extensions, forSolution: true);
70+
private async Task ShowInstallForSolutionDialogAsync(IInstallWorker worker, IManifest manifest, IReadOnlyCollection<VSExtensionToInstall> extensions, bool forSolution)
6971
{
7072
var vm = new InstallDialogViewModel(worker, manifest, forSolution);
7173

72-
foreach (var ext in manifest.Extensions)
74+
foreach (var (extension, status) in extensions)
7375
{
74-
var isInstalled = installedExtensions.Contains(ext, ExtensionEqualityComparerById.Instance);
76+
switch (status)
77+
{
78+
case VSExtensionStatus.Installed:
79+
vm.AddExtension(extension, canBeSelected: false, group: "Already installed");
80+
break;
81+
82+
case VSExtensionStatus.NotInstalled:
83+
vm.AddExtension(extension, canBeSelected: true, group: "Extensions");
84+
break;
85+
86+
case VSExtensionStatus.NotSupported:
87+
vm.AddExtension(extension, canBeSelected: false, group: "Not supported");
88+
break;
7589

76-
vm.AddExtension(ext, isInstalled);
90+
default:
91+
throw new InvalidOperationException($"Unknown status {status} for extension {extension.Id}");
92+
}
7793
}
7894

7995
await ShowInstallExportDialogAsync(vm);

src/ExtensionManager.UI/IDialogService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ public interface IDialogService
1111

1212
Task ShowExportDialogAsync(IExportWorker worker, IManifest manifest, IReadOnlyCollection<IVSExtension> installedExtensions);
1313
Task ShowExportForSolutionDialogAsync(IExportWorker worker, IManifest manifest, IReadOnlyCollection<IVSExtension> installedExtensions);
14-
Task ShowInstallDialogAsync(IInstallWorker worker, IManifest manifest, IReadOnlyCollection<IVSExtension> installedExtensions);
15-
Task ShowInstallForSolutionDialogAsync(IInstallWorker worker, IManifest manifest, IReadOnlyCollection<IVSExtension> installedExtensions);
14+
Task ShowInstallDialogAsync(IInstallWorker worker, IManifest manifest, IReadOnlyCollection<VSExtensionToInstall> extensions);
15+
Task ShowInstallForSolutionDialogAsync(IInstallWorker worker, IManifest manifest, IReadOnlyCollection<VSExtensionToInstall> extensions);
1616
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace ExtensionManager.UI;
2+
3+
public enum VSExtensionStatus
4+
{
5+
Unknown,
6+
Installed,
7+
NotInstalled,
8+
NotSupported,
9+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
using ExtensionManager.VisualStudio.Extensions;
2+
3+
namespace ExtensionManager.UI;
4+
5+
public record struct VSExtensionToInstall(IVSExtension Extension, VSExtensionStatus Status);

src/ExtensionManager.UI/ViewModels/InstallDialogViewModel.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ public InstallDialogViewModel(IInstallWorker worker, IManifest manifest, bool fo
1818
_manifest = manifest;
1919
}
2020

21-
public void AddExtension(IVSExtension extension, bool isInstalled)
21+
public void AddExtension(IVSExtension extension, bool canBeSelected, string? group)
2222
{
2323
Extensions.Add(new(extension)
2424
{
25-
CanBeSelected = !isInstalled,
26-
Group = isInstalled ? "Already installed" : "Extensions",
25+
CanBeSelected = canBeSelected,
26+
Group = group,
2727
});
2828
}
2929

src/ExtensionManager.UI/Views/InstallExportDialogWindow.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@
183183
<Grid.Resources>
184184
<CollectionViewSource x:Key="ExtensionsSource" Source="{Binding Extensions}">
185185
<CollectionViewSource.SortDescriptions>
186-
<scm:SortDescription PropertyName="Group" Direction="Descending" />
186+
<scm:SortDescription PropertyName="CanBeSelected" Direction="Descending" />
187187
</CollectionViewSource.SortDescriptions>
188188

189189
<CollectionViewSource.GroupDescriptions>

src/ExtensionManager/Features/Export/ExportFeature.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ public ExportFeature(Args args)
1414
protected override async Task<string?> GetFilePathAsync()
1515
=> await DialogService.ShowSaveVsextFileDialogAsync();
1616

17-
protected override async Task ShowExportDialogAsync(IManifest manifest, IExportWorker worker, IReadOnlyCollection<IVSExtension> installedExtensions)
18-
=> await DialogService.ShowExportDialogAsync(worker, manifest, installedExtensions);
17+
protected override async Task ShowExportDialogAsync(IManifest manifest, IExportWorker worker, IReadOnlyCollection<IVSExtension> extensions)
18+
=> await DialogService.ShowExportDialogAsync(worker, manifest, extensions);
1919

2020
protected override async Task OnManifestWrittenAsync(string filePath)
2121
=> await Documents.OpenAsync(filePath);

src/ExtensionManager/Features/Install/InstallFeature.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using ExtensionManager.Manifest;
2+
using ExtensionManager.UI;
23
using ExtensionManager.UI.Worker;
3-
using ExtensionManager.VisualStudio.Extensions;
44

55
namespace ExtensionManager.Features.Install;
66

@@ -14,6 +14,6 @@ public InstallFeature(Args args)
1414
protected override async Task<string?> GetFilePathAsync()
1515
=> await DialogService.ShowOpenVsextFileDialogAsync();
1616

17-
protected override async Task ShowInstallDialogAsync(IManifest manifest, IInstallWorker worker, IReadOnlyCollection<IVSExtension> installedExtensions)
18-
=> await DialogService.ShowInstallDialogAsync(worker, manifest, installedExtensions);
17+
protected override async Task ShowInstallDialogAsync(IManifest manifest, IInstallWorker worker, IReadOnlyCollection<VSExtensionToInstall> extensions)
18+
=> await DialogService.ShowInstallDialogAsync(worker, manifest, extensions);
1919
}

src/ExtensionManager/Features/Install/InstallFeatureBase.cs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using ExtensionManager.Manifest;
33
using ExtensionManager.UI;
44
using ExtensionManager.UI.Worker;
5+
using ExtensionManager.Utils;
56
using ExtensionManager.VisualStudio.Extensions;
67
using ExtensionManager.VisualStudio.MessageBox;
78

@@ -50,10 +51,32 @@ public async Task ExecuteAsync()
5051
if (!File.Exists(filePath))
5152
return;
5253

53-
var installedExtensions = await Extensions.GetInstalledExtensionsAsync().ConfigureAwait(false);
5454
var manifest = await ManifestService.ReadAsync(filePath).ConfigureAwait(false);
55+
var extensionsToInstall = await CreateExtensionsToInstallListAsync(manifest.Extensions).ConfigureAwait(false);
5556

56-
await ShowInstallDialogAsync(manifest, this, installedExtensions);
57+
await ShowInstallDialogAsync(manifest, this, extensionsToInstall);
58+
}
59+
60+
private async Task<IReadOnlyList<VSExtensionToInstall>> CreateExtensionsToInstallListAsync(IEnumerable<IVSExtension> toInstall)
61+
{
62+
var installed = await Extensions.GetInstalledExtensionsAsync().ConfigureAwait(false);
63+
var gallery = await Extensions.GetGalleryExtensionsAsync(toInstall.Select(x => x.Id)).ConfigureAwait(false);
64+
65+
var statuses = new Dictionary<string, VSExtensionStatus>();
66+
67+
foreach (var extension in toInstall)
68+
statuses[extension.Id] = VSExtensionStatus.NotSupported;
69+
70+
foreach (var extension in gallery)
71+
statuses[extension.Id] = VSExtensionStatus.NotInstalled;
72+
73+
foreach (var extension in installed.Intersect(toInstall, ExtensionEqualityComparer.Instance))
74+
statuses[extension.Id] = VSExtensionStatus.Installed;
75+
76+
return toInstall
77+
.Distinct(ExtensionEqualityComparer.Instance)
78+
.Select(x => new VSExtensionToInstall(x, statuses[x.Id]))
79+
.ToList();
5780
}
5881

5982
async Task IInstallWorker.InstallAsync(IManifest manifest, IReadOnlyCollection<IVSExtension> extensions, bool systemWide, IProgress<ProgressStep<InstallStep>> progress, CancellationToken cancellationToken)
@@ -63,5 +86,5 @@ async Task IInstallWorker.InstallAsync(IManifest manifest, IReadOnlyCollection<I
6386
}
6487

6588
protected abstract Task<string?> GetFilePathAsync();
66-
protected abstract Task ShowInstallDialogAsync(IManifest manifest, IInstallWorker worker, IReadOnlyCollection<IVSExtension> installedExtensions);
89+
protected abstract Task ShowInstallDialogAsync(IManifest manifest, IInstallWorker worker, IReadOnlyCollection<VSExtensionToInstall> extensions);
6790
}

src/ExtensionManager/Features/Install/InstallForSolutionFeature.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using ExtensionManager.Manifest;
2+
using ExtensionManager.UI;
23
using ExtensionManager.UI.Worker;
3-
using ExtensionManager.VisualStudio.Extensions;
44
using ExtensionManager.VisualStudio.Solution;
55

66
namespace ExtensionManager.Features.Install;
@@ -18,6 +18,6 @@ public InstallForSolutionFeature(Args args, IVSSolutions solutions)
1818
protected override async Task<string?> GetFilePathAsync()
1919
=> await _solutions.GetCurrentSolutionExtensionsManifestFilePathAsync(MessageBox);
2020

21-
protected override async Task ShowInstallDialogAsync(IManifest manifest, IInstallWorker worker, IReadOnlyCollection<IVSExtension> installedExtensions)
22-
=> await DialogService.ShowInstallForSolutionDialogAsync(worker, manifest, installedExtensions);
21+
protected override async Task ShowInstallDialogAsync(IManifest manifest, IInstallWorker worker, IReadOnlyCollection<VSExtensionToInstall> extensions)
22+
=> await DialogService.ShowInstallForSolutionDialogAsync(worker, manifest, extensions);
2323
}

0 commit comments

Comments
 (0)