Skip to content

Commit 8ff8030

Browse files
authored
Merge pull request #3 from zdpcdt/ui
add Client & Upgrade UI
2 parents ab66315 + e1aee9f commit 8ff8030

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1417
-0
lines changed

src/Client.Avalonia/App.axaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<Application xmlns="https://github.com/avaloniaui"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3+
x:Class="Client.Avalonia.App"
4+
xmlns:local="using:Client.Avalonia"
5+
xmlns:semi="https://irihi.tech/semi">
6+
<Application.DataTemplates>
7+
<local:ViewLocator />
8+
</Application.DataTemplates>
9+
10+
<Application.Styles>
11+
<semi:SemiTheme Locale="zh-CN" />
12+
</Application.Styles>
13+
14+
<Application.Resources>
15+
<ResourceDictionary>
16+
<ResourceDictionary.MergedDictionaries>
17+
<ResourceInclude Source="avares://Common.Avalonia/Themes/Resources/_index.axaml" />
18+
<ResourceInclude Source="avares://Common.Avalonia/Themes/Controls/_index.axaml" />
19+
</ResourceDictionary.MergedDictionaries>
20+
</ResourceDictionary>
21+
</Application.Resources>
22+
</Application>

src/Client.Avalonia/App.axaml.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using System;
2+
using System.Linq;
3+
using Avalonia;
4+
using Avalonia.Controls.ApplicationLifetimes;
5+
using Avalonia.Data.Core.Plugins;
6+
using Avalonia.Markup.Xaml;
7+
using Client.Avalonia.ViewModels;
8+
using Client.Avalonia.Views;
9+
using Common.Avalonia.Services;
10+
using Microsoft.Extensions.DependencyInjection;
11+
12+
namespace Client.Avalonia;
13+
14+
public partial class App : Application
15+
{
16+
public static IServiceProvider? ServiceProvider { get; private set; }
17+
18+
public override void Initialize()
19+
{
20+
AvaloniaXamlLoader.Load(this);
21+
}
22+
23+
public override void OnFrameworkInitializationCompleted()
24+
{
25+
var services = new ServiceCollection();
26+
services.AddSingleton<IDownloadService, MockDownloadService>();
27+
services.AddTransient<MainViewViewModel>();
28+
ServiceProvider = new DefaultServiceProviderFactory().CreateServiceProvider(services);
29+
30+
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
31+
{
32+
// Avoid duplicate validations from both Avalonia and the CommunityToolkit.
33+
// More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins
34+
DisableAvaloniaDataAnnotationValidation();
35+
desktop.MainWindow = new MainWindow();
36+
}
37+
38+
base.OnFrameworkInitializationCompleted();
39+
}
40+
41+
private void DisableAvaloniaDataAnnotationValidation()
42+
{
43+
// Get an array of plugins to remove
44+
var dataValidationPluginsToRemove =
45+
BindingPlugins.DataValidators.OfType<DataAnnotationsValidationPlugin>().ToArray();
46+
47+
// remove each entry found
48+
foreach (var plugin in dataValidationPluginsToRemove)
49+
{
50+
BindingPlugins.DataValidators.Remove(plugin);
51+
}
52+
}
53+
}
16.3 KB
Loading
Lines changed: 56 additions & 0 deletions
Loading
172 KB
Binary file not shown.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>WinExe</OutputType>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
7+
<ApplicationManifest>app.manifest</ApplicationManifest>
8+
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<AvaloniaResource Include="Assets\**"/>
13+
</ItemGroup>
14+
15+
<ItemGroup>
16+
<PackageReference Include="Avalonia" Version="11.2.2"/>
17+
<PackageReference Include="Avalonia.Desktop" Version="11.2.2"/>
18+
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
19+
<PackageReference Include="Avalonia.Diagnostics" Version="11.2.2">
20+
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
21+
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
22+
</PackageReference>
23+
<PackageReference Include="Avalonia.Svg" Version="11.2.0.2"/>
24+
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2"/>
25+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0"/>
26+
<PackageReference Include="Semi.Avalonia" Version="11.2.1.1"/>
27+
</ItemGroup>
28+
29+
<ItemGroup>
30+
<ProjectReference Include="..\Common.Avalonia\Common.Avalonia.csproj"/>
31+
</ItemGroup>
32+
</Project>

src/Client.Avalonia/Program.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using Avalonia;
2+
using System;
3+
4+
namespace Client.Avalonia;
5+
6+
sealed class Program
7+
{
8+
// Initialization code. Don't use any Avalonia, third-party APIs or any
9+
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
10+
// yet and stuff might break.
11+
[STAThread]
12+
public static void Main(string[] args) => BuildAvaloniaApp()
13+
.StartWithClassicDesktopLifetime(args);
14+
15+
// Avalonia configuration, don't remove; also used by visual designer.
16+
public static AppBuilder BuildAvaloniaApp()
17+
=> AppBuilder.Configure<App>()
18+
.UsePlatformDetect()
19+
.LogToTrace();
20+
}

src/Client.Avalonia/ViewLocator.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System;
2+
using Avalonia.Controls;
3+
using Avalonia.Controls.Templates;
4+
using Client.Avalonia.ViewModels;
5+
6+
namespace Client.Avalonia;
7+
8+
public class ViewLocator : IDataTemplate
9+
{
10+
public Control? Build(object? param)
11+
{
12+
if (param is null)
13+
return null;
14+
15+
var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal);
16+
var type = Type.GetType(name);
17+
18+
if (type != null)
19+
{
20+
return (Control)Activator.CreateInstance(type)!;
21+
}
22+
23+
return new TextBlock { Text = "Not Found: " + name };
24+
}
25+
26+
public bool Match(object? data)
27+
{
28+
return data is ViewModelBase;
29+
}
30+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using Avalonia;
2+
using Avalonia.Controls;
3+
using Avalonia.Controls.ApplicationLifetimes;
4+
using Avalonia.Controls.Notifications;
5+
using Common.Avalonia.Models;
6+
using Common.Avalonia.Services;
7+
using CommunityToolkit.Mvvm.ComponentModel;
8+
using CommunityToolkit.Mvvm.Input;
9+
10+
namespace Client.Avalonia.ViewModels;
11+
12+
public partial class MainViewViewModel : ViewModelBase
13+
{
14+
private readonly IDownloadService _downloadService;
15+
private readonly WindowNotificationManager _notificationManager;
16+
17+
[ObservableProperty] private DownloadStatistics _statistics;
18+
19+
[ObservableProperty] [NotifyCanExecuteChangedFor(nameof(StartCommand), nameof(StopCommand))]
20+
private DownloadStatus _status;
21+
22+
public MainViewViewModel(IDownloadService downloadService)
23+
{
24+
_downloadService = downloadService;
25+
_notificationManager = new WindowNotificationManager(ResolveDefaultTopLevel());
26+
27+
_downloadService.ProgressChanged += stats => Statistics = stats;
28+
_downloadService.StatusChanged += status => Status = status;
29+
_downloadService.DownloadCompleted += OnDownloadCompleted;
30+
31+
Statistics = _downloadService.CurrentStatistics;
32+
Status = _downloadService.Status;
33+
}
34+
35+
#region Buttons
36+
37+
private bool CanStart => Status is DownloadStatus.NotStarted or DownloadStatus.Downloading or DownloadStatus.Paused;
38+
39+
[RelayCommand(CanExecute = nameof(CanStart))]
40+
private void Start() => _downloadService.Start();
41+
42+
private bool CanStop => Status is DownloadStatus.Downloading or DownloadStatus.Paused;
43+
44+
[RelayCommand(CanExecute = nameof(CanStop))]
45+
private void Stop() => _downloadService.Stop();
46+
47+
[RelayCommand]
48+
private void Restart() => _downloadService.Restart();
49+
50+
#endregion
51+
52+
private void OnDownloadCompleted()
53+
{
54+
_notificationManager.Show(new Notification(
55+
"更新完成",
56+
$"已更新到最新版本,版本号:{Statistics.Version}",
57+
NotificationType.Success));
58+
}
59+
60+
private static TopLevel? ResolveDefaultTopLevel()
61+
{
62+
return Application.Current?.ApplicationLifetime switch
63+
{
64+
IClassicDesktopStyleApplicationLifetime desktop => desktop.MainWindow,
65+
ISingleViewApplicationLifetime singleView => TopLevel.GetTopLevel(singleView.MainView),
66+
_ => null
67+
};
68+
}
69+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
namespace Client.Avalonia.ViewModels;
2+
3+
public partial class MainWindowViewModel : ViewModelBase;

0 commit comments

Comments
 (0)