diff --git a/global.json b/global.json
index c358071f0..abe582084 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "10.0.103",
- "rollForward": "latestPatch"
+ "rollForward": "latestFeature"
}
}
diff --git a/src/UniGetUI.Avalonia/UniGetUI.Avalonia.csproj b/src/UniGetUI.Avalonia/UniGetUI.Avalonia.csproj
index 94884fca7..2514a337f 100644
--- a/src/UniGetUI.Avalonia/UniGetUI.Avalonia.csproj
+++ b/src/UniGetUI.Avalonia/UniGetUI.Avalonia.csproj
@@ -94,7 +94,7 @@
-
+
diff --git a/src/UniGetUI.Avalonia/ViewModels/MainWindowViewModel.cs b/src/UniGetUI.Avalonia/ViewModels/MainWindowViewModel.cs
index 4b3ccba2d..62d59ffaf 100644
--- a/src/UniGetUI.Avalonia/ViewModels/MainWindowViewModel.cs
+++ b/src/UniGetUI.Avalonia/ViewModels/MainWindowViewModel.cs
@@ -108,13 +108,11 @@ partial void OnGlobalSearchTextChanged(string value)
private void SubscribeToPageViewModel(AbstractPackagesPage? page)
{
- if (_subscribedPageViewModel is not null)
- _subscribedPageViewModel.PropertyChanged -= OnPageViewModelPropertyChanged;
+ _subscribedPageViewModel?.PropertyChanged -= OnPageViewModelPropertyChanged;
_subscribedPageViewModel = page?.ViewModel;
- if (_subscribedPageViewModel is not null)
- _subscribedPageViewModel.PropertyChanged += OnPageViewModelPropertyChanged;
+ _subscribedPageViewModel?.PropertyChanged += OnPageViewModelPropertyChanged;
}
private void OnPageViewModelPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
diff --git a/src/UniGetUI.Avalonia/Views/Controls/InfoBar.axaml.cs b/src/UniGetUI.Avalonia/Views/Controls/InfoBar.axaml.cs
index c62c57fb7..6602b1996 100644
--- a/src/UniGetUI.Avalonia/Views/Controls/InfoBar.axaml.cs
+++ b/src/UniGetUI.Avalonia/Views/Controls/InfoBar.axaml.cs
@@ -23,16 +23,13 @@ public InfoBar()
private void OnDataContextChanged(object? sender, EventArgs e)
{
- if (_vm is not null)
- _vm.PropertyChanged -= OnViewModelPropertyChanged;
+ _vm?.PropertyChanged -= OnViewModelPropertyChanged;
_vm = DataContext as InfoBarViewModel;
+ _vm?.PropertyChanged += OnViewModelPropertyChanged;
if (_vm is not null)
- {
- _vm.PropertyChanged += OnViewModelPropertyChanged;
ApplySeverity(_vm.Severity);
- }
}
private void OnViewModelPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/PingetCliHelper.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/PingetCliHelper.cs
index dd87579b7..3796ed563 100644
--- a/src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/PingetCliHelper.cs
+++ b/src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/PingetCliHelper.cs
@@ -18,7 +18,6 @@ internal sealed partial class PingetCliHelper : IWinGetManagerHelper
private static readonly JsonSerializerOptions SerializationOptions = new()
{
PropertyNameCaseInsensitive = true,
- PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
};
private static readonly PingetCliJsonContext SerializationContext = new(SerializationOptions);
@@ -55,7 +54,7 @@ public IReadOnlyList GetAvailableUpdates_UnSafe()
match.Id,
match.InstalledVersion,
match.AvailableVersion!,
- GetSource(match.SourceName, match.Id),
+ GetSource(match),
Manager
);
@@ -87,7 +86,7 @@ public IReadOnlyList GetInstalledPackages_UnSafe()
match.Name,
match.Id,
match.InstalledVersion,
- GetSource(match.SourceName, match.Id),
+ GetSource(match),
Manager
)
)
@@ -234,6 +233,32 @@ internal static T DeserializeJson(string output)
: throw new InvalidOperationException("Pinget returned empty JSON output.");
}
+ internal static string? InferSourceName(ListMatch match)
+ {
+ if (!string.IsNullOrWhiteSpace(match.SourceName))
+ {
+ return match.SourceName;
+ }
+
+ if (match.Id.Contains("_Microsoft.Winget.Source_8wekyb3d8bbwe", StringComparison.OrdinalIgnoreCase))
+ {
+ return "winget";
+ }
+
+ if (!string.IsNullOrWhiteSpace(match.InstallLocation)
+ && match.InstallLocation.Contains("\\Microsoft\\WinGet\\Packages\\", StringComparison.OrdinalIgnoreCase))
+ {
+ return "winget";
+ }
+
+ return null;
+ }
+
+ private IManagerSource GetSource(ListMatch match)
+ {
+ return GetSource(InferSourceName(match), match.Id);
+ }
+
private IManagerSource GetSource(string? sourceName, string packageId)
{
if (string.IsNullOrWhiteSpace(sourceName))
diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/PingetPackageDetailsProvider.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/PingetPackageDetailsProvider.cs
index 44205ba2b..0f9804384 100644
--- a/src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/PingetPackageDetailsProvider.cs
+++ b/src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/PingetPackageDetailsProvider.cs
@@ -84,10 +84,10 @@ private IReadOnlyList GetSourceNames(INativeTaskLogger logger)
{
try
{
- string output = RunPinget(["source", "list", "--output", "json"], logger);
+ string output = RunPinget(["source", "export", "--output", "json"], logger);
using JsonDocument document = JsonDocument.Parse(output);
if (
- !document.RootElement.TryGetProperty("sources", out JsonElement sources)
+ !document.RootElement.TryGetProperty("Sources", out JsonElement sources)
|| sources.ValueKind != JsonValueKind.Array
)
{
@@ -97,7 +97,7 @@ private IReadOnlyList GetSourceNames(INativeTaskLogger logger)
return sources
.EnumerateArray()
.Select(source =>
- source.TryGetProperty("name", out JsonElement name)
+ source.TryGetProperty("Name", out JsonElement name)
? name.GetString()
: null
)
diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/UniGetUI.PackageEngine.Managers.WinGet.csproj b/src/UniGetUI.PackageEngine.Managers.WinGet/UniGetUI.PackageEngine.Managers.WinGet.csproj
index dba42cc45..76720dd8c 100644
--- a/src/UniGetUI.PackageEngine.Managers.WinGet/UniGetUI.PackageEngine.Managers.WinGet.csproj
+++ b/src/UniGetUI.PackageEngine.Managers.WinGet/UniGetUI.PackageEngine.Managers.WinGet.csproj
@@ -24,7 +24,7 @@
-
+
diff --git a/src/UniGetUI.PackageEngine.Tests/WinGetManagerTests.cs b/src/UniGetUI.PackageEngine.Tests/WinGetManagerTests.cs
index aeafbbe82..de73fd0b5 100644
--- a/src/UniGetUI.PackageEngine.Tests/WinGetManagerTests.cs
+++ b/src/UniGetUI.PackageEngine.Tests/WinGetManagerTests.cs
@@ -300,28 +300,28 @@ public void FindCandidateExecutableFilesReturnsEmptyWhenNoCliToolExists()
[Fact]
public void PingetCliHelperDeserializesListResponsesWithGeneratedContext()
{
- // pinget 0.4.1+ emits snake_case keys.
+ // Pinget emits PascalCase keys.
const string json = """
{
- "matches": [
+ "Matches": [
{
- "name": "Contoso Tool",
- "id": "Contoso.Tool",
- "local_id": null,
- "installed_version": "1.2.3",
- "available_version": "2.0.0",
- "source_name": "winget",
- "publisher": null,
- "scope": null,
- "installer_category": null,
- "install_location": null,
- "package_family_names": [],
- "product_codes": [],
- "upgrade_codes": []
+ "Name": "Contoso Tool",
+ "Id": "Contoso.Tool",
+ "LocalId": null,
+ "InstalledVersion": "1.2.3",
+ "AvailableVersion": "2.0.0",
+ "SourceName": "winget",
+ "Publisher": null,
+ "Scope": null,
+ "InstallerCategory": null,
+ "InstallLocation": null,
+ "PackageFamilyNames": [],
+ "ProductCodes": [],
+ "UpgradeCodes": []
}
],
- "warnings": [],
- "truncated": false
+ "Warnings": [],
+ "Truncated": false
}
""";
@@ -335,6 +335,38 @@ public void PingetCliHelperDeserializesListResponsesWithGeneratedContext()
Assert.Equal("winget", match.SourceName);
}
+ [Fact]
+ public void PingetCliHelperInfersWingetSourceWhenInstalledSourceNameIsMissing()
+ {
+ const string json = """
+ {
+ "Matches": [
+ {
+ "Name": "Contoso Tool",
+ "Id": "ARP\\User\\X64\\Contoso.Tool_Microsoft.Winget.Source_8wekyb3d8bbwe",
+ "LocalId": null,
+ "InstalledVersion": "1.2.3",
+ "AvailableVersion": null,
+ "SourceName": null,
+ "Publisher": "Contoso",
+ "Scope": "User",
+ "InstallerCategory": "exe",
+ "InstallLocation": "C:\\Users\\example\\AppData\\Local\\Microsoft\\WinGet\\Packages\\Contoso.Tool_Microsoft.Winget.Source_8wekyb3d8bbwe",
+ "PackageFamilyNames": [],
+ "ProductCodes": [],
+ "UpgradeCodes": []
+ }
+ ],
+ "Warnings": [],
+ "Truncated": false
+ }
+ """;
+
+ ListMatch match = Assert.Single(PingetCliHelper.DeserializeJson(json).Matches);
+
+ Assert.Equal("winget", PingetCliHelper.InferSourceName(match));
+ }
+
[Fact]
public void GetCliToolPreferenceUsesEnvironmentBeforeSettings()
{
diff --git a/src/UniGetUI/Controls/PackageItemContainer.cs b/src/UniGetUI/Controls/PackageItemContainer.cs
index 485cc662f..5d440ab1c 100644
--- a/src/UniGetUI/Controls/PackageItemContainer.cs
+++ b/src/UniGetUI/Controls/PackageItemContainer.cs
@@ -17,15 +17,9 @@ public PackageWrapper Wrapper
get => _wrapper;
set
{
- if (_wrapper != null)
- {
- _wrapper.PropertyChanged -= Wrapper_PropertyChanged;
- }
+ _wrapper?.PropertyChanged -= Wrapper_PropertyChanged;
_wrapper = value;
- if (_wrapper != null)
- {
- _wrapper.PropertyChanged += Wrapper_PropertyChanged;
- }
+ _wrapper?.PropertyChanged += Wrapper_PropertyChanged;
}
}
diff --git a/src/UniGetUI/UniGetUI.csproj b/src/UniGetUI/UniGetUI.csproj
index 917c3844e..0a25ced00 100644
--- a/src/UniGetUI/UniGetUI.csproj
+++ b/src/UniGetUI/UniGetUI.csproj
@@ -221,7 +221,7 @@
-
+