From a868177261f47be4ce6c6c359b53c066093f0661 Mon Sep 17 00:00:00 2001 From: Kevin B Date: Sat, 5 Oct 2024 23:17:34 -0700 Subject: [PATCH] Avalonia template updates (#220) * Updating Avalonia app to use DI Fixed up the browser target to match the latest Avalonia template. * Adding avalonia GHA test * Bumping released version * Restore dotnet workloads * Trying the workload on macOS * Also test on windows --- .github/workflows/build.yml | 27 ++++++- Templates.csproj | 2 +- .../AvaloniaSolution/Directory.Packages.props | 8 +- .../AppBundle/Logo.svg | 5 -- .../AppBundle/app.css | 74 ------------------ .../AppBundle/index.html | 30 ------- .../Program.cs | 1 - .../Properties/AssemblyInfo.cs | 1 + .../Properties/launchSettings.json | 4 +- .../SampleAvaloniaApplication.Browser.csproj | 11 +-- .../runtimeconfig.template.json | 3 +- .../wwwroot/app.css | 58 ++++++++++++++ .../{AppBundle => wwwroot}/favicon.ico | Bin .../wwwroot/index.html | 36 +++++++++ .../{AppBundle => wwwroot}/main.js | 4 +- .../SampleAvaloniaApplication/App.axaml.cs | 26 +++--- .../SampleAvaloniaApplication.csproj | 1 + .../ServiceCollectionExtensions.cs | 63 +++++++++++++++ .../ViewModels/MainViewModel.cs | 13 ++- .../ViewModels/ViewModelBase.cs | 7 -- .../Views/MainView.axaml | 6 +- .../Views/MainView.axaml.cs | 8 ++ .../Views/MainWindow.axaml | 1 - .../Views/MainWindow.axaml.cs | 6 ++ 24 files changed, 242 insertions(+), 153 deletions(-) delete mode 100644 templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication.Browser/AppBundle/Logo.svg delete mode 100644 templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication.Browser/AppBundle/app.css delete mode 100644 templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication.Browser/AppBundle/index.html create mode 100644 templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication.Browser/Properties/AssemblyInfo.cs create mode 100644 templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication.Browser/wwwroot/app.css rename templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication.Browser/{AppBundle => wwwroot}/favicon.ico (100%) create mode 100644 templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication.Browser/wwwroot/index.html rename templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication.Browser/{AppBundle => wwwroot}/main.js (69%) create mode 100644 templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication/ServiceCollectionExtensions.cs delete mode 100644 templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication/ViewModels/ViewModelBase.cs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4f07a1a..7c17904 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -110,6 +110,31 @@ jobs: dotnet test dotnet pack --configuration Release -o ./NuGet + test-avalonia: + runs-on: windows-latest + needs: build + + steps: + - name: Download NuGet Artifacts + uses: actions/download-artifact@v4 + with: + name: NuGet + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Test Template + run: | + dotnet new install $(Get-ChildItem -Path "Keboo.Dotnet.Templates.*.nupkg").Name + mkdir TestAvalonia + Push-Location TestAvalonia + dotnet new keboo.avalonia + dotnet workload restore + dotnet build + + automerge: if: ${{ github.event_name == 'pull_request' }} runs-on: ubuntu-latest @@ -127,7 +152,7 @@ jobs: if: ${{ github.event_name != 'pull_request' }} name: Push NuGets runs-on: ubuntu-latest - needs: [build, test-console, test-wpf, test-library] + needs: [build, test-console, test-wpf, test-library, test-avalonia] steps: - name: Download NuGet Artifacts diff --git a/Templates.csproj b/Templates.csproj index 4c1c5c5..d0db691 100644 --- a/Templates.csproj +++ b/Templates.csproj @@ -2,7 +2,7 @@ Template - 1.7.1 + 1.7.2 Keboo.Dotnet.Templates Keboo's .NET Templates Keboo diff --git a/templates/Avalonia/AvaloniaSolution/Directory.Packages.props b/templates/Avalonia/AvaloniaSolution/Directory.Packages.props index b920a83..8157fcc 100644 --- a/templates/Avalonia/AvaloniaSolution/Directory.Packages.props +++ b/templates/Avalonia/AvaloniaSolution/Directory.Packages.props @@ -8,16 +8,13 @@ Uncomment if you need to enable inclusion of another Directory.Packages.props file from a parent directory --> - true true - 11.1.3 - diff --git a/templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication/ServiceCollectionExtensions.cs b/templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..a751ccc --- /dev/null +++ b/templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication/ServiceCollectionExtensions.cs @@ -0,0 +1,63 @@ +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Controls; +using Avalonia.Threading; + +using Microsoft.Extensions.DependencyInjection; +using Avalonia; +using SampleAvaloniaApplication.Views; +using SampleAvaloniaApplication.ViewModels; + +namespace SampleAvaloniaApplication; + +public static class ServiceCollectionExtensions +{ + public static void AddServices(this IServiceCollection services) + { + services.AddAvaloniaServices(); + services.AddViews(); + } + + private static void AddAvaloniaServices(this IServiceCollection services) + { + services.AddSingleton(_ => Dispatcher.UIThread); + services.AddSingleton(_ => Application.Current?.ApplicationLifetime ?? NoopApplicationLifetime.Instance); + + services.AddSingleton(sp => + sp.GetRequiredService() switch + { + IClassicDesktopStyleApplicationLifetime desktop => desktop.MainWindow ?? throw new InvalidOperationException("No main window set"), + ISingleViewApplicationLifetime singleViewPlatform => TopLevel.GetTopLevel(singleViewPlatform.MainView) ?? throw new InvalidOperationException("Could not find top level element for single view"), + _ => throw new InvalidOperationException($"Could not find {nameof(TopLevel)} element"), + } + ); + + services.AddSingleton(sp => sp.GetRequiredService().StorageProvider); + } + + private static void AddViews(this IServiceCollection services) + { + //NB: Window is only needed for Desktop + services.AddTransient(); + + services.AddView(); + } + + private static void AddView(this IServiceCollection services) + where TView : class + where TViewModel : class + { + services.AddTransient(); + services.AddTransient(); + } + + private sealed class NoopApplicationLifetime : IDisposable, IApplicationLifetime + { + private static readonly Lazy _instance = new(() => new NoopApplicationLifetime()); + public static IApplicationLifetime Instance => _instance.Value; + + private NoopApplicationLifetime() + { } + + public void Dispose() { } + } +} diff --git a/templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication/ViewModels/MainViewModel.cs b/templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication/ViewModels/MainViewModel.cs index fc90ae6..d418fcd 100644 --- a/templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication/ViewModels/MainViewModel.cs +++ b/templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication/ViewModels/MainViewModel.cs @@ -1,6 +1,15 @@ -namespace SampleAvaloniaApplication.ViewModels; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; -public partial class MainViewModel : ViewModelBase +namespace SampleAvaloniaApplication.ViewModels; + +public partial class MainViewModel : ObservableObject { public string Greeting => "Welcome to Avalonia!"; + + [ObservableProperty] + private int _counter; + + [RelayCommand] + public void Increment() => Counter++; } diff --git a/templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication/ViewModels/ViewModelBase.cs b/templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication/ViewModels/ViewModelBase.cs deleted file mode 100644 index 9382104..0000000 --- a/templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication/ViewModels/ViewModelBase.cs +++ /dev/null @@ -1,7 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; - -namespace SampleAvaloniaApplication.ViewModels; - -public class ViewModelBase : ObservableObject -{ -} diff --git a/templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication/Views/MainView.axaml b/templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication/Views/MainView.axaml index df22e83..fd44384 100644 --- a/templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication/Views/MainView.axaml +++ b/templates/Avalonia/AvaloniaSolution/SampleAvaloniaApplication/Views/MainView.axaml @@ -12,5 +12,9 @@ - + + + +