mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-22 09:14:25 +08:00
settings_re9
This commit is contained in:
@@ -7,7 +7,7 @@ using Avalonia.Media.Imaging;
|
||||
|
||||
namespace LanMountainDesktop.Services.PluginMarket;
|
||||
|
||||
internal sealed class AirAppMarketIconService : IDisposable
|
||||
public sealed class AirAppMarketIconService : IDisposable
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
@@ -20,7 +20,7 @@ internal sealed class AirAppMarketIconService : IDisposable
|
||||
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("LanMountainDesktop-PluginMarketplace/1.0");
|
||||
}
|
||||
|
||||
public async Task<Bitmap> LoadAsync(
|
||||
internal async Task<Bitmap> LoadAsync(
|
||||
AirAppMarketPluginEntry plugin,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
@@ -40,6 +40,26 @@ internal sealed class AirAppMarketIconService : IDisposable
|
||||
return new Bitmap(memory);
|
||||
}
|
||||
|
||||
public async Task<Bitmap> LoadAsync(
|
||||
LanMountainDesktop.Services.Settings.PluginMarketPluginInfo plugin,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(plugin);
|
||||
|
||||
if (AirAppMarketDefaults.TryResolveWorkspaceFile(plugin.IconUrl, out var localIconPath))
|
||||
{
|
||||
return new Bitmap(localIconPath);
|
||||
}
|
||||
|
||||
using var response = await _httpClient.GetAsync(plugin.IconUrl, cancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken);
|
||||
using var memory = new MemoryStream();
|
||||
await stream.CopyToAsync(memory, cancellationToken);
|
||||
memory.Position = 0;
|
||||
return new Bitmap(memory);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_httpClient.Dispose();
|
||||
|
||||
@@ -438,6 +438,29 @@ internal sealed class AirAppMarketSharedContractEntry
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class AirAppMarketPluginDependencyEntry
|
||||
{
|
||||
public string Id { get; init; } = string.Empty;
|
||||
|
||||
public string Version { get; init; } = string.Empty;
|
||||
|
||||
public string AssemblyName { get; init; } = string.Empty;
|
||||
|
||||
public AirAppMarketPluginDependencyEntry ValidateAndNormalize(string sourceName)
|
||||
{
|
||||
return new AirAppMarketPluginDependencyEntry
|
||||
{
|
||||
Id = AirAppMarketIndexDocument.NormalizeValue(Id)
|
||||
?? throw new InvalidOperationException(
|
||||
$"Market index '{sourceName}' is missing dependency id for a plugin entry."),
|
||||
Version = AirAppMarketIndexDocument.NormalizeVersion(Version, nameof(Version), sourceName),
|
||||
AssemblyName = AirAppMarketIndexDocument.NormalizeValue(AssemblyName)
|
||||
?? throw new InvalidOperationException(
|
||||
$"Market index '{sourceName}' is missing assemblyName for dependency '{Id}'.")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class AirAppMarketPluginEntry
|
||||
{
|
||||
public string Id { get; init; } = string.Empty;
|
||||
@@ -476,6 +499,8 @@ internal sealed class AirAppMarketPluginEntry
|
||||
|
||||
public List<string> Tags { get; init; } = [];
|
||||
|
||||
public List<AirAppMarketPluginDependencyEntry> SharedContracts { get; init; } = [];
|
||||
|
||||
public DateTimeOffset PublishedAt { get; init; }
|
||||
|
||||
public DateTimeOffset UpdatedAt { get; init; }
|
||||
@@ -495,6 +520,21 @@ internal sealed class AirAppMarketPluginEntry
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.OrderBy(tag => tag, StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
var normalizedDependencies = new List<AirAppMarketPluginDependencyEntry>((SharedContracts ?? []).Count);
|
||||
var seenDependencies = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var dependency in SharedContracts ?? [])
|
||||
{
|
||||
var normalizedDependency = dependency.ValidateAndNormalize(sourceName);
|
||||
var dependencyKey = $"{normalizedDependency.Id}@{normalizedDependency.Version}";
|
||||
if (!seenDependencies.Add(dependencyKey))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Market index '{sourceName}' declares duplicate dependency '{dependencyKey}' for plugin '{Id}'.");
|
||||
}
|
||||
|
||||
normalizedDependencies.Add(normalizedDependency);
|
||||
}
|
||||
|
||||
var normalizedSha = AirAppMarketIndexDocument.NormalizeValue(Sha256)?.ToLowerInvariant()
|
||||
?? throw new InvalidOperationException(
|
||||
@@ -590,6 +630,7 @@ internal sealed class AirAppMarketPluginEntry
|
||||
HomepageUrl = normalizedHomepageUrl,
|
||||
RepositoryUrl = normalizedRepositoryUrl,
|
||||
Tags = normalizedTags,
|
||||
SharedContracts = normalizedDependencies,
|
||||
PublishedAt = PublishedAt,
|
||||
UpdatedAt = UpdatedAt,
|
||||
ReleaseNotes = AirAppMarketIndexDocument.NormalizeValue(ReleaseNotes)
|
||||
|
||||
@@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace LanMountainDesktop.Services.PluginMarket;
|
||||
|
||||
internal sealed class AirAppMarketReadmeService : IDisposable
|
||||
public sealed class AirAppMarketReadmeService : IDisposable
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
@@ -19,7 +19,7 @@ internal sealed class AirAppMarketReadmeService : IDisposable
|
||||
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("LanMountainDesktop-PluginMarketplace/1.0");
|
||||
}
|
||||
|
||||
public async Task<string> LoadAsync(
|
||||
internal async Task<string> LoadAsync(
|
||||
AirAppMarketPluginEntry plugin,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
@@ -35,6 +35,22 @@ internal sealed class AirAppMarketReadmeService : IDisposable
|
||||
return await response.Content.ReadAsStringAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<string> LoadAsync(
|
||||
LanMountainDesktop.Services.Settings.PluginMarketPluginInfo plugin,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(plugin);
|
||||
|
||||
if (AirAppMarketDefaults.TryResolveWorkspaceFile(plugin.ReadmeUrl, out var localReadmePath))
|
||||
{
|
||||
return await File.ReadAllTextAsync(localReadmePath, cancellationToken);
|
||||
}
|
||||
|
||||
using var response = await _httpClient.GetAsync(plugin.ReadmeUrl, cancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
return await response.Content.ReadAsStringAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_httpClient.Dispose();
|
||||
|
||||
Reference in New Issue
Block a user