mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-22 09:14:25 +08:00
0.5.10
多线程
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
namespace LanMountainDesktop.Views;
|
||||
|
||||
public partial class MainWindow
|
||||
{
|
||||
private void ApplyPluginMarketSettingsLocalization()
|
||||
{
|
||||
PluginMarketSettingsPanel.RefreshFromRuntime();
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ public partial class MainWindow
|
||||
.GroupBy(contribution => contribution.Plugin.Manifest.Id, StringComparer.OrdinalIgnoreCase)
|
||||
.ToDictionary(group => group.Key, group => group.Count(), StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
var insertIndex = SettingsNavView.MenuItems.IndexOf(SettingsNavPluginsItem) + 1;
|
||||
var insertIndex = SettingsNavView.MenuItems.IndexOf(SettingsNavPluginMarketItem) + 1;
|
||||
foreach (var contribution in contributions)
|
||||
{
|
||||
var tag = BuildPluginSettingsTag(contribution);
|
||||
|
||||
@@ -14,6 +14,7 @@ internal sealed class AirAppMarketInstallService : IDisposable
|
||||
{
|
||||
private readonly PluginRuntimeService _runtime;
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly ResumableDownloadService _downloadService;
|
||||
private readonly AirAppMarketReleaseResolverService _releaseResolverService;
|
||||
private readonly string _downloadsDirectory;
|
||||
|
||||
@@ -26,6 +27,7 @@ internal sealed class AirAppMarketInstallService : IDisposable
|
||||
Timeout = TimeSpan.FromMinutes(2)
|
||||
};
|
||||
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("LanMountainDesktop-PluginMarketplace/1.0");
|
||||
_downloadService = new ResumableDownloadService(_httpClient);
|
||||
_releaseResolverService = new AirAppMarketReleaseResolverService(_httpClient);
|
||||
}
|
||||
|
||||
@@ -46,21 +48,27 @@ internal sealed class AirAppMarketInstallService : IDisposable
|
||||
|
||||
if (AirAppMarketDefaults.TryResolveWorkspaceFile(resolvedDownloadUrl, out var localPackagePath))
|
||||
{
|
||||
await using var sourceStream = File.OpenRead(localPackagePath);
|
||||
await using var destinationStream = File.Create(downloadPath);
|
||||
await sourceStream.CopyToAsync(destinationStream, cancellationToken);
|
||||
var localCopyResult = await _downloadService.DownloadAsync(
|
||||
localPackagePath,
|
||||
downloadPath,
|
||||
new DownloadOptions(ExpectedSizeBytes: plugin.PackageSizeBytes),
|
||||
cancellationToken: cancellationToken);
|
||||
if (!localCopyResult.Success)
|
||||
{
|
||||
return new AirAppMarketInstallResult(false, null, localCopyResult.ErrorMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using var response = await _httpClient.GetAsync(
|
||||
var downloadResult = await _downloadService.DownloadAsync(
|
||||
resolvedDownloadUrl,
|
||||
HttpCompletionOption.ResponseHeadersRead,
|
||||
cancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
await using var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken);
|
||||
await using var destinationStream = File.Create(downloadPath);
|
||||
await responseStream.CopyToAsync(destinationStream, cancellationToken);
|
||||
downloadPath,
|
||||
new DownloadOptions(ExpectedSizeBytes: plugin.PackageSizeBytes),
|
||||
cancellationToken: cancellationToken);
|
||||
if (!downloadResult.Success)
|
||||
{
|
||||
return new AirAppMarketInstallResult(false, null, downloadResult.ErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
await using var hashStream = File.OpenRead(downloadPath);
|
||||
|
||||
25
LanMountainDesktop/plugins/PluginMarketSettingsPage.axaml
Normal file
25
LanMountainDesktop/plugins/PluginMarketSettingsPage.axaml
Normal file
@@ -0,0 +1,25 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="960"
|
||||
d:DesignHeight="1000"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.PluginMarketSettingsPage">
|
||||
|
||||
<StackPanel x:Name="PluginMarketPanel"
|
||||
Spacing="16">
|
||||
<TextBlock x:Name="PluginMarketPanelTitleTextBlock"
|
||||
FontSize="24"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}"
|
||||
Text="Plugin Market" />
|
||||
|
||||
<TextBlock x:Name="PluginMarketPanelSubtitleTextBlock"
|
||||
Foreground="{DynamicResource AdaptiveTextSecondaryBrush}"
|
||||
TextWrapping="Wrap"
|
||||
Text="Browse plugins from the official LanAirApp source and stage installs." />
|
||||
|
||||
<ContentControl x:Name="PluginMarketContentHost" />
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
71
LanMountainDesktop/plugins/PluginMarketSettingsPage.axaml.cs
Normal file
71
LanMountainDesktop/plugins/PluginMarketSettingsPage.axaml.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
using LanMountainDesktop.Services;
|
||||
|
||||
namespace LanMountainDesktop.Views.SettingsPages;
|
||||
|
||||
public partial class PluginMarketSettingsPage : UserControl
|
||||
{
|
||||
private readonly AppSettingsService _appSettingsService = new();
|
||||
private readonly LocalizationService _localizationService = new();
|
||||
private PluginMarketEmbeddedView? _pluginMarketView;
|
||||
|
||||
public PluginMarketSettingsPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
AttachedToVisualTree += (_, _) => RefreshFromRuntime();
|
||||
}
|
||||
|
||||
public void RefreshFromRuntime()
|
||||
{
|
||||
PluginMarketPanelTitleTextBlock.Text = L("settings.plugin_market.title", "Plugin Market");
|
||||
PluginMarketPanelSubtitleTextBlock.Text = L(
|
||||
"settings.plugin_market.subtitle",
|
||||
"Browse plugins from the official LanAirApp source and stage installs.");
|
||||
|
||||
var runtime = (Application.Current as App)?.PluginRuntimeService;
|
||||
if (runtime is null)
|
||||
{
|
||||
PluginMarketContentHost.Content = CreateUnavailableState();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_pluginMarketView is null)
|
||||
{
|
||||
_pluginMarketView = new PluginMarketEmbeddedView(runtime);
|
||||
}
|
||||
|
||||
_pluginMarketView.RefreshLocalization();
|
||||
_pluginMarketView.RefreshInstalledSnapshot();
|
||||
|
||||
if (!ReferenceEquals(PluginMarketContentHost.Content, _pluginMarketView))
|
||||
{
|
||||
PluginMarketContentHost.Content = _pluginMarketView;
|
||||
}
|
||||
}
|
||||
|
||||
private Control CreateUnavailableState()
|
||||
{
|
||||
return new Border
|
||||
{
|
||||
Background = new SolidColorBrush(Color.Parse("#14000000")),
|
||||
CornerRadius = new CornerRadius(16),
|
||||
Padding = new Thickness(16),
|
||||
Child = new TextBlock
|
||||
{
|
||||
Text = L(
|
||||
"settings.plugin_market.unavailable",
|
||||
"Plugin runtime is not available, so the official market cannot be opened right now."),
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
Foreground = PluginMarketPanelSubtitleTextBlock.Foreground
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private string L(string key, string fallback)
|
||||
{
|
||||
var snapshot = _appSettingsService.Load();
|
||||
return _localizationService.GetString(snapshot.LanguageCode, key, fallback);
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@ public partial class PluginSettingsPage : UserControl
|
||||
|
||||
private readonly AppSettingsService _appSettingsService = new();
|
||||
private readonly LocalizationService _localizationService = new();
|
||||
private PluginMarketEmbeddedView? _pluginMarketView;
|
||||
private string? _packageImportStatusMessage;
|
||||
private bool _packageImportStatusIsError;
|
||||
|
||||
@@ -34,13 +33,6 @@ public partial class PluginSettingsPage : UserControl
|
||||
public void RefreshFromRuntime()
|
||||
{
|
||||
var runtime = (Application.Current as App)?.PluginRuntimeService;
|
||||
PluginMarketSettingsExpander.Header = L("settings.plugins.market_header", "Official Market");
|
||||
PluginMarketSettingsExpander.Description = L(
|
||||
"settings.plugins.market_desc",
|
||||
"Browse plugins from the official LanAirApp source and stage installs.");
|
||||
PluginMarketDescriptionTextBlock.Text = L(
|
||||
"settings.plugins.market_hint",
|
||||
"Use the official market source hosted in LanAirApp to discover and stage plugin installs.");
|
||||
UpdateInstallerUi(runtime);
|
||||
if (runtime is null)
|
||||
{
|
||||
@@ -48,33 +40,13 @@ public partial class PluginSettingsPage : UserControl
|
||||
PluginRuntimeSummaryPanel.Children.Clear();
|
||||
PluginCatalogItemsHost.Children.Clear();
|
||||
PluginRestartHintTextBlock.IsVisible = false;
|
||||
PluginMarketContentHost.Content = CreateSummaryLine(
|
||||
L("settings.plugins.market_unavailable", "Plugin runtime is not available, so the official market cannot be opened right now."));
|
||||
return;
|
||||
}
|
||||
|
||||
EnsurePluginMarketView(runtime);
|
||||
_pluginMarketView?.RefreshLocalization();
|
||||
_pluginMarketView?.RefreshInstalledSnapshot();
|
||||
BuildRuntimeSummary(runtime);
|
||||
BuildPluginCatalog(runtime);
|
||||
}
|
||||
|
||||
private void EnsurePluginMarketView(PluginRuntimeService runtime)
|
||||
{
|
||||
if (_pluginMarketView is null)
|
||||
{
|
||||
_pluginMarketView = new PluginMarketEmbeddedView(runtime);
|
||||
PluginMarketContentHost.Content = _pluginMarketView;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ReferenceEquals(PluginMarketContentHost.Content, _pluginMarketView))
|
||||
{
|
||||
PluginMarketContentHost.Content = _pluginMarketView;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateInstallerUi(PluginRuntimeService? runtime)
|
||||
{
|
||||
InstallPluginPackageButton.Content = L("settings.plugins.install_button", "Open .laapp package");
|
||||
|
||||
@@ -83,24 +83,5 @@
|
||||
</ui:SettingsExpander>
|
||||
</Border>
|
||||
|
||||
<Border Classes="settings-expander-shell">
|
||||
<ui:SettingsExpander x:Name="PluginMarketSettingsExpander"
|
||||
Header="Official Market"
|
||||
Description="Browse plugins from the official LanAirApp source and stage installs."
|
||||
IsExpanded="True">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<ui:FontIconSource Glyph="" FontFamily="{StaticResource SymbolThemeFontFamily}" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<StackPanel Spacing="10">
|
||||
<TextBlock x:Name="PluginMarketDescriptionTextBlock"
|
||||
Foreground="{DynamicResource AdaptiveTextSecondaryBrush}"
|
||||
TextWrapping="Wrap"
|
||||
Text="Use the official market source hosted in LanAirApp to discover and stage plugin installs." />
|
||||
<ContentControl x:Name="PluginMarketContentHost" />
|
||||
</StackPanel>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace LanMountainDesktop.Views;
|
||||
|
||||
public partial class SettingsWindow
|
||||
{
|
||||
private void ApplyPluginMarketSettingsLocalization()
|
||||
{
|
||||
PluginMarketSettingsPanel.RefreshFromRuntime();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user