From 4fc0b56cc7b77d25d5678c55ec8121bf98f6ea04 Mon Sep 17 00:00:00 2001 From: OmnipotentOwl <1769881+OmnipotentOwl@users.noreply.github.com> Date: Sat, 25 Sep 2021 20:39:29 -0400 Subject: [PATCH 01/41] Add Sextant Maui Project --- src/Sextant.Maui/Behaviors/BehaviorBase.cs | 68 ++++++ .../NavigationPageSystemPopBehavior.cs | 72 ++++++ .../Mixins/DependencyResolverMixins.cs | 108 +++++++++ src/Sextant.Maui/Mixins/SextantExtensions.cs | 34 +++ src/Sextant.Maui/NavigationSource.cs | 23 ++ src/Sextant.Maui/NavigationView.cs | 228 ++++++++++++++++++ src/Sextant.Maui/Sextant.Maui.csproj | 26 ++ src/Sextant.sln | 12 +- 8 files changed, 568 insertions(+), 3 deletions(-) create mode 100644 src/Sextant.Maui/Behaviors/BehaviorBase.cs create mode 100644 src/Sextant.Maui/Behaviors/NavigationPageSystemPopBehavior.cs create mode 100644 src/Sextant.Maui/Mixins/DependencyResolverMixins.cs create mode 100644 src/Sextant.Maui/Mixins/SextantExtensions.cs create mode 100644 src/Sextant.Maui/NavigationSource.cs create mode 100644 src/Sextant.Maui/NavigationView.cs create mode 100644 src/Sextant.Maui/Sextant.Maui.csproj diff --git a/src/Sextant.Maui/Behaviors/BehaviorBase.cs b/src/Sextant.Maui/Behaviors/BehaviorBase.cs new file mode 100644 index 00000000..f73ce54c --- /dev/null +++ b/src/Sextant.Maui/Behaviors/BehaviorBase.cs @@ -0,0 +1,68 @@ +// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System; +using System.Reactive.Disposables; +using System.Reactive.Linq; +using Microsoft.Maui.Controls; + +namespace Sextant.Maui +{ + /// + /// Represents and abstract . + /// + /// The bindable object type. + /// + public abstract class BehaviorBase : Behavior, IDisposable + where T : BindableObject + { + /// + /// Gets the disposables for this behavior. + /// + protected CompositeDisposable BehaviorDisposable { get; } = new(); + + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + protected override void OnAttachedTo(T bindable) + { + base.OnAttachedTo(bindable); + Observable.FromEvent( + handler => + { + void Handler(object sender, EventArgs args) => handler(args); + return Handler!; + }, + x => bindable.BindingContextChanged += x, + x => bindable.BindingContextChanged -= x) + .Subscribe(_ => BindingContext = bindable.BindingContext) + .DisposeWith(BehaviorDisposable); + } + + /// + protected override void OnDetachingFrom(T bindable) + { + base.OnDetachingFrom(bindable); + Dispose(); + } + + /// + /// Disposes of resources. + /// + /// A value indicating where this instance is disposing. + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + BehaviorDisposable.Dispose(); + } + } + } +} diff --git a/src/Sextant.Maui/Behaviors/NavigationPageSystemPopBehavior.cs b/src/Sextant.Maui/Behaviors/NavigationPageSystemPopBehavior.cs new file mode 100644 index 00000000..28bfca9d --- /dev/null +++ b/src/Sextant.Maui/Behaviors/NavigationPageSystemPopBehavior.cs @@ -0,0 +1,72 @@ +// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System; +using System.Reactive.Disposables; +using System.Reactive.Linq; +using Microsoft.Maui.Controls; + +namespace Sextant.Maui +{ + /// + /// Represents a that intercepts the backwards navigation. + /// + public sealed class NavigationPageSystemPopBehavior : BehaviorBase + { + private readonly IObservable _navigationSource; + + /// + /// Initializes a new instance of the class. + /// + /// A value indicating whether the back button was pressed. + public NavigationPageSystemPopBehavior(IObservable navigationSource) => + _navigationSource = navigationSource; + + /// + protected override void OnAttachedTo(NavigationPage bindable) + { + Observable + .FromEvent, NavigationEventArgs>( + handler => + { + void Handler(object sender, NavigationEventArgs args) => handler(args); + return Handler!; + }, + x => bindable.Popped += x, + x => bindable.Popped -= x) + .WithLatestFrom(_navigationSource, (navigated, navigationSource) => (navigated, navigationSource)) + .Where(result => result.navigationSource == NavigationSource.Device) + .Select(x => x.navigated) + .Subscribe(navigated => + { + INavigationParameter navigationParameter = new NavigationParameter(); + + navigated + .Page + .BindingContext + .InvokeViewModelAction(x => + x.WhenNavigatedFrom(navigationParameter) + .Subscribe() + .DisposeWith(BehaviorDisposable)); + + bindable + .CurrentPage + .BindingContext + .InvokeViewModelAction(x => + x.WhenNavigatedTo(navigationParameter) + .Subscribe() + .DisposeWith(BehaviorDisposable)); + + navigated + .Page + .BindingContext + .InvokeViewModelAction(x => x.Destroy()); + }) + .DisposeWith(BehaviorDisposable); + + base.OnAttachedTo(bindable); + } + } +} diff --git a/src/Sextant.Maui/Mixins/DependencyResolverMixins.cs b/src/Sextant.Maui/Mixins/DependencyResolverMixins.cs new file mode 100644 index 00000000..ec7c0b73 --- /dev/null +++ b/src/Sextant.Maui/Mixins/DependencyResolverMixins.cs @@ -0,0 +1,108 @@ +// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Reactive.Concurrency; +using ReactiveUI; +using Splat; + +namespace Sextant.Maui +{ + /// + /// Extension methods associated with the IMutableDependencyResolver interface. + /// + public static class DependencyResolverMixins + { + /// + /// Gets the navigation view key. + /// + [SuppressMessage("Design", "CA1721: Confusing name, should be method.", Justification = "Deliberate usage.")] + public static string NavigationView => nameof(NavigationView); + + /// + /// Initializes the sextant. + /// + /// The dependency resolver. + /// The dependencyResolver. + public static IMutableDependencyResolver RegisterNavigationView(this IMutableDependencyResolver dependencyResolver) + { + dependencyResolver.RegisterLazySingleton( + () => new NavigationView( + RxApp.MainThreadScheduler, + RxApp.TaskpoolScheduler, + Locator.Current.GetService() ?? throw new InvalidOperationException("IViewLocator not registered.")), + typeof(IView), + NavigationView); + return dependencyResolver; + } + + /// + /// Initializes sextant. + /// + /// The dependency resolver. + /// The main scheduler. + /// The background scheduler. + /// The dependencyResolver. + public static IMutableDependencyResolver RegisterNavigationView(this IMutableDependencyResolver dependencyResolver, IScheduler mainThreadScheduler, IScheduler backgroundScheduler) + { + dependencyResolver.RegisterLazySingleton( + () => new NavigationView( + mainThreadScheduler, + backgroundScheduler, + Locator.Current.GetService() ?? throw new InvalidOperationException("IViewLocator not registered.")), + typeof(IView), + NavigationView); + return dependencyResolver; + } + + /// + /// Registers a value for navigation. + /// + /// The type of view to register. + /// The dependency resolver. + /// The navigation view factory. + /// The dependencyResolver. + [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "Long term object.")] + public static IMutableDependencyResolver RegisterNavigationView(this IMutableDependencyResolver dependencyResolver, Func navigationViewFactory) + where TView : IView + { + if (dependencyResolver is null) + { + throw new ArgumentNullException(nameof(dependencyResolver)); + } + + if (navigationViewFactory is null) + { + throw new ArgumentNullException(nameof(navigationViewFactory)); + } + + var navigationView = navigationViewFactory(); + var viewStackService = new ViewStackService(navigationView); + + dependencyResolver.RegisterLazySingleton(() => viewStackService); + dependencyResolver.RegisterLazySingleton(() => navigationView, NavigationView); + return dependencyResolver; + } + + /// + /// Gets the navigation view. + /// + /// The dependency resolver. + /// The contract. + /// The navigation view. + public static NavigationView? GetNavigationView( + this IReadonlyDependencyResolver dependencyResolver, + string? contract = null) + { + if (dependencyResolver is null) + { + throw new ArgumentNullException(nameof(dependencyResolver)); + } + + return dependencyResolver.GetService(contract ?? NavigationView) as NavigationView; + } + } +} diff --git a/src/Sextant.Maui/Mixins/SextantExtensions.cs b/src/Sextant.Maui/Mixins/SextantExtensions.cs new file mode 100644 index 00000000..78bf0fe1 --- /dev/null +++ b/src/Sextant.Maui/Mixins/SextantExtensions.cs @@ -0,0 +1,34 @@ +// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System; + +namespace Sextant.Maui +{ + /// + /// Extension methods interact with . + /// + public static class SextantExtensions + { + /// + /// Initializes the sextant. + /// + /// The sextant. + public static void InitializeForms(this Sextant sextant) + { + if (sextant is null) + { + throw new ArgumentNullException(nameof(sextant)); + } + + sextant + .MutableLocator + .RegisterNavigationView() + .RegisterViewStackService() + .RegisterParameterViewStackService() + .RegisterViewModelFactory(() => new DefaultViewModelFactory()); + } + } +} diff --git a/src/Sextant.Maui/NavigationSource.cs b/src/Sextant.Maui/NavigationSource.cs new file mode 100644 index 00000000..3b2a2c09 --- /dev/null +++ b/src/Sextant.Maui/NavigationSource.cs @@ -0,0 +1,23 @@ +// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace Sextant.Maui +{ + /// + /// An enumeration of where navigation signals are sent from. + /// + public enum NavigationSource + { + /// + /// Navigation sourced from the device. + /// + Device, + + /// + /// Navigation sourced from the service. + /// + NavigationService + } +} diff --git a/src/Sextant.Maui/NavigationView.cs b/src/Sextant.Maui/NavigationView.cs new file mode 100644 index 00000000..ef852aba --- /dev/null +++ b/src/Sextant.Maui/NavigationView.cs @@ -0,0 +1,228 @@ +// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System; +using System.Reactive; +using System.Reactive.Concurrency; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Reactive.Threading.Tasks; +using Microsoft.Maui.Controls; +using ReactiveUI; +using Splat; + +namespace Sextant.Maui +{ + /// + /// The main navigation view. + /// + public class NavigationView : NavigationPage, IView, IEnableLogger + { + private readonly ISubject _navigationSource = + new BehaviorSubject(NavigationSource.Device); + + private readonly IScheduler _backgroundScheduler; + private readonly IViewLocator _viewLocator; + private readonly IFullLogger _logger; + + /// + /// Initializes a new instance of the class. + /// + public NavigationView() + : this(RxApp.MainThreadScheduler, RxApp.TaskpoolScheduler, ViewLocator.Current) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The main scheduler to scheduler UI tasks on. + /// The background scheduler. + /// The view locator which will find views associated with view models. + /// The starting root page. + public NavigationView(IScheduler mainScheduler, IScheduler backgroundScheduler, IViewLocator viewLocator, Page rootPage) + : base(rootPage) + { + _backgroundScheduler = backgroundScheduler; + MainThreadScheduler = mainScheduler; + _viewLocator = viewLocator; + _logger = this.Log(); + + PagePopped = + Observable + .FromEvent, IViewModel>( + handler => + { + void Handler(object? sender, NavigationEventArgs args) + { + if (args.Page.BindingContext is IViewModel viewModel) + { + handler(viewModel); + } + } + + return Handler; + }, + x => Popped += x, + x => Popped -= x); + + Behaviors.Add(new NavigationPageSystemPopBehavior(_navigationSource.AsObservable())); + } + + /// + /// Initializes a new instance of the class. + /// + /// The main scheduler to scheduler UI tasks on. + /// The background scheduler. + /// The view locator which will find views associated with view models. + public NavigationView(IScheduler mainScheduler, IScheduler backgroundScheduler, IViewLocator viewLocator) + { + MainThreadScheduler = mainScheduler; + _backgroundScheduler = backgroundScheduler; + _viewLocator = viewLocator; + _logger = this.Log(); + + PagePopped = + Observable + .FromEvent, IViewModel>( + handler => + { + void Handler(object? sender, NavigationEventArgs args) + { + if (args.Page.BindingContext is IViewModel viewModel) + { + handler(viewModel); + } + } + + return Handler; + }, + x => Popped += x, + x => Popped -= x); + + Behaviors.Add(new NavigationPageSystemPopBehavior(_navigationSource.AsObservable())); + } + + /// + public IScheduler MainThreadScheduler { get; } + + /// + public IObservable PagePopped { get; } + + /// + public IObservable PopModal() => + Navigation + .PopModalAsync() + .ToObservable() + .Select(_ => Unit.Default) + .ObserveOn(MainThreadScheduler); // XF completes the pop operation on a background thread :/ + + /// + public IObservable PopPage(bool animate) + { + _navigationSource.OnNext(NavigationSource.NavigationService); + + return Navigation + .PopAsync(animate) + .ToObservable() + .Select(_ => Unit.Default) + .ObserveOn(MainThreadScheduler) + .Finally(() => _navigationSource.OnNext(NavigationSource.Device)); + } + + /// + public IObservable PopToRootPage(bool animate) => + Navigation + .PopToRootAsync(animate) + .ToObservable() + .Select(_ => Unit.Default) + .ObserveOn(MainThreadScheduler); + + /// + public IObservable PushModal(IViewModel modalViewModel, string? contract, bool withNavigationPage = true) => + Observable + .Start( + () => + { + var page = LocatePageFor(modalViewModel, contract); + SetPageTitle(page, modalViewModel.Id); + return withNavigationPage ? new NavigationPage(page) : page; + }, + CurrentThreadScheduler.Instance) + .ObserveOn(CurrentThreadScheduler.Instance) + .SelectMany( + page => + Navigation + .PushModalAsync(page) + .ToObservable()); + + /// + public IObservable PushPage( + IViewModel viewModel, + string? contract, + bool resetStack, + bool animate) => + Observable + .Start( + () => + { + var page = LocatePageFor(viewModel, contract); + SetPageTitle(page, viewModel.Id); + return page; + }, + CurrentThreadScheduler.Instance) + .ObserveOn(CurrentThreadScheduler.Instance) + .SelectMany( + page => + { + if (resetStack) + { + if (Navigation.NavigationStack.Count == 0) + { + return Navigation.PushAsync(page, false).ToObservable(); + } + + // XF does not allow us to pop to a new root page. Instead, we need to inject the new root page and then pop to it. + Navigation + .InsertPageBefore(page, Navigation.NavigationStack[0]); + + return Navigation + .PopToRootAsync(false) + .ToObservable(); + } + + return Navigation + .PushAsync(page, animate) + .ToObservable(); + }); + + private static void SetPageTitle(Page page, string resourceKey) => + + // var title = Localize.GetString(resourceKey); + // TODO: ensure resourceKey isn't null and is localized. + page.Title = resourceKey; + + private Page LocatePageFor(object viewModel, string? contract) + { + var view = _viewLocator.ResolveView(viewModel, contract); + + if (view is null) + { + throw new InvalidOperationException( + $"No view could be located for type '{viewModel.GetType().FullName}', contract '{contract}'. Be sure Splat has an appropriate registration."); + } + + if (!(view is Page page)) + { + throw new InvalidOperationException( + $"Resolved view '{view.GetType().FullName}' for type '{viewModel.GetType().FullName}', contract '{contract}' is not a Page."); + } + + view.ViewModel = viewModel; + + return page; + } + } +} diff --git a/src/Sextant.Maui/Sextant.Maui.csproj b/src/Sextant.Maui/Sextant.Maui.csproj new file mode 100644 index 00000000..525d3263 --- /dev/null +++ b/src/Sextant.Maui/Sextant.Maui.csproj @@ -0,0 +1,26 @@ + + + + net6.0 + enable + Sextant.Maui + Sextant.Maui + Sextant.Maui + enable + latest + + + + + + + + + + + + + + + + diff --git a/src/Sextant.sln b/src/Sextant.sln index e36b06cc..3f9e2ed3 100644 --- a/src/Sextant.sln +++ b/src/Sextant.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29521.150 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31717.71 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sextant", "Sextant\Sextant.csproj", "{D6B84899-4AFC-4E6C-9C3F-005F21DF5A52}" EndProject @@ -32,7 +32,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sextant.Plugins.Popup", "Se EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sextant.Plugins.Popup.Tests", "Sextant.Plugins.Popup.Tests\Sextant.Plugins.Popup.Tests.csproj", "{BD186721-EE51-40B2-A546-91EDDE122998}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sextant.Avalonia", "Sextant.Avalonia\Sextant.Avalonia.csproj", "{A91CDEEB-C4D5-402B-9B42-D91E0151F30E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sextant.Avalonia", "Sextant.Avalonia\Sextant.Avalonia.csproj", "{A91CDEEB-C4D5-402B-9B42-D91E0151F30E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sextant.Maui", "Sextant.Maui\Sextant.Maui.csproj", "{EFD457DB-C7FC-446C-AD85-3F22493C275C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -74,6 +76,10 @@ Global {A91CDEEB-C4D5-402B-9B42-D91E0151F30E}.Debug|Any CPU.Build.0 = Debug|Any CPU {A91CDEEB-C4D5-402B-9B42-D91E0151F30E}.Release|Any CPU.ActiveCfg = Release|Any CPU {A91CDEEB-C4D5-402B-9B42-D91E0151F30E}.Release|Any CPU.Build.0 = Release|Any CPU + {EFD457DB-C7FC-446C-AD85-3F22493C275C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EFD457DB-C7FC-446C-AD85-3F22493C275C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EFD457DB-C7FC-446C-AD85-3F22493C275C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EFD457DB-C7FC-446C-AD85-3F22493C275C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From d6d65667808c60a3c29ebcb45c508adc63344765 Mon Sep 17 00:00:00 2001 From: OmnipotentOwl <1769881+OmnipotentOwl@users.noreply.github.com> Date: Sun, 26 Sep 2021 09:33:00 -0400 Subject: [PATCH 02/41] Update github pipelines for supporting net6 maui --- .github/workflows/build-samples.yml | 38 +++++++++++++++++++++++++++- .github/workflows/ci-build.yml | 39 ++++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-samples.yml b/.github/workflows/build-samples.yml index 30c596a7..fe0b59c4 100644 --- a/.github/workflows/build-samples.yml +++ b/.github/workflows/build-samples.yml @@ -12,9 +12,28 @@ jobs: matrix: configuration: [Debug, Release] - runs-on: windows-latest + runs-on: windows-2022 steps: + - name: Update VS2022 preview + shell: bash + run: | + dotnet tool update -g dotnet-vs + vs modify preview +mobile +xamarin +core +desktop +uwp +web + echo "##vso[task.prependpath]$(vs where preview --prop=InstallationPath)\MSBuild\Current\Bin" + + - name: Install Windows SDK 10.0.16299 + shell: pwsh + run: | + Invoke-WebRequest -Uri https://go.microsoft.com/fwlink/p/?linkid=864422 -OutFile winsdk.exe + $startInfo = New-Object System.Diagnostics.ProcessStartInfo + $startInfo.FileName = "winsdk.exe" + $startInfo.Arguments = "/norestart /quiet" + $process = New-Object System.Diagnostics.Process + $process.StartInfo = $startInfo + $process.Start() + $process.WaitForExit() + - name: Checkout uses: actions/checkout@v2 with: @@ -32,6 +51,23 @@ jobs: with: dotnet-version: 5.0.x + - name: Install .NET 6 + uses: actions/setup-dotnet@v1.8.2 + with: + dotnet-version: 6.0.x + include-prerelease: true + + - name: Install DotNet workloads + shell: bash + run: | + dotnet workload install android + dotnet workload install ios + dotnet workload install tvos + dotnet workload install macos + dotnet workload install maui + dotnet tool install -g Redth.Net.Maui.Check + maui-check --non-interactive --fix + # Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild - name: Setup MSBuild.exe uses: microsoft/setup-msbuild@v1.0.2 diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 984c4177..1f60c3bb 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -13,10 +13,29 @@ env: jobs: build: - runs-on: windows-latest + runs-on: windows-2022 outputs: nbgv: ${{ steps.nbgv.outputs.SemVer2 }} steps: + - name: Update VS2022 preview + shell: bash + run: | + dotnet tool update -g dotnet-vs + vs modify preview +mobile +xamarin +core +desktop +uwp +web + echo "##vso[task.prependpath]$(vs where preview --prop=InstallationPath)\MSBuild\Current\Bin" + + - name: Install Windows SDK 10.0.16299 + shell: pwsh + run: | + Invoke-WebRequest -Uri https://go.microsoft.com/fwlink/p/?linkid=864422 -OutFile winsdk.exe + $startInfo = New-Object System.Diagnostics.ProcessStartInfo + $startInfo.FileName = "winsdk.exe" + $startInfo.Arguments = "/norestart /quiet" + $process = New-Object System.Diagnostics.Process + $process.StartInfo = $startInfo + $process.Start() + $process.WaitForExit() + - name: Checkout uses: actions/checkout@v2 with: @@ -32,6 +51,24 @@ jobs: uses: actions/setup-dotnet@v1 with: dotnet-version: 5.0.x + + - name: Install .NET 6 + uses: actions/setup-dotnet@v1.8.2 + with: + dotnet-version: 6.0.x + include-prerelease: true + + - name: Install DotNet workloads + shell: bash + run: | + dotnet workload install android + dotnet workload install ios + dotnet workload install tvos + dotnet workload install macos + dotnet workload install maui + dotnet workload restore "src/ReactiveUI/ReactiveUI.csproj" + dotnet tool install -g Redth.Net.Maui.Check + maui-check --non-interactive --fix - name: Add MSBuild to PATH uses: glennawatson/setup-msbuild@v1.0.3 From a2063fce669f01d1c2e7690c0a111bb86aed8893 Mon Sep 17 00:00:00 2001 From: OmnipotentOwl <1769881+OmnipotentOwl@users.noreply.github.com> Date: Sun, 26 Sep 2021 09:33:31 -0400 Subject: [PATCH 03/41] Fix maui project type to match design from reactiveui.maui --- src/Sextant.Maui/Sextant.Maui.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Sextant.Maui/Sextant.Maui.csproj b/src/Sextant.Maui/Sextant.Maui.csproj index 525d3263..f0f491a9 100644 --- a/src/Sextant.Maui/Sextant.Maui.csproj +++ b/src/Sextant.Maui/Sextant.Maui.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -11,7 +11,7 @@ - + From 82f1c094d467b8220d8de4c96f9d3680b3cc082d Mon Sep 17 00:00:00 2001 From: OmnipotentOwl <1769881+OmnipotentOwl@users.noreply.github.com> Date: Sun, 26 Sep 2021 10:08:33 -0400 Subject: [PATCH 04/41] Update main Sextant library to support net6 maui --- src/Directory.build.targets | 13 ++++++++ .../Platforms/android/SextantExtensions.cs | 29 ++++++++++++++++ .../Platforms/mac/SextantExtensions.cs | 33 +++++++++++++++++++ src/Sextant/Sextant.csproj | 28 +++++++++++++--- 4 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 src/Sextant/Platforms/android/SextantExtensions.cs create mode 100644 src/Sextant/Platforms/mac/SextantExtensions.cs diff --git a/src/Directory.build.targets b/src/Directory.build.targets index 7469e6b5..2f999897 100644 --- a/src/Directory.build.targets +++ b/src/Directory.build.targets @@ -8,23 +8,36 @@ $(DefineConstants);NET_45;XAML + 10.0.16299.0 $(DefineConstants);NETFX_CORE;XAML;WINDOWS_UWP $(DefineConstants);MONO;UIKIT;COCOA + + $(DefineConstants);MONO;UIKIT;COCOA;IOS + $(DefineConstants);MONO;COCOA + + $(DefineConstants);MONO;COCOA;MAC + $(DefineConstants);MONO;UIKIT;COCOA + + $(DefineConstants);MONO;UIKIT;COCOA;TVOS + $(DefineConstants);MONO;UIKIT;COCOA $(DefineConstants);MONO;ANDROID + + $(DefineConstants);MONO;ANDROID + $(DefineConstants);TIZEN diff --git a/src/Sextant/Platforms/android/SextantExtensions.cs b/src/Sextant/Platforms/android/SextantExtensions.cs new file mode 100644 index 00000000..b11ec829 --- /dev/null +++ b/src/Sextant/Platforms/android/SextantExtensions.cs @@ -0,0 +1,29 @@ +// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System; + +namespace Sextant +{ + /// + /// Extensions methods to setup the instance. + /// + public static class SextantExtensions + { + /// + /// Initializes the specified sextant. + /// + /// The sextant. + public static void Initialize(this Sextant sextant) + { + if (sextant is null) + { + throw new ArgumentNullException(nameof(sextant)); + } + + sextant.MutableLocator.RegisterViewStackService(); + } + } +} diff --git a/src/Sextant/Platforms/mac/SextantExtensions.cs b/src/Sextant/Platforms/mac/SextantExtensions.cs new file mode 100644 index 00000000..2eb978a9 --- /dev/null +++ b/src/Sextant/Platforms/mac/SextantExtensions.cs @@ -0,0 +1,33 @@ +// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.Reactive.Concurrency; +using System.Text; +using Splat; + +namespace Sextant +{ + /// + /// Extensions methods to setup the instance. + /// + public static class SextantExtensions + { + /// + /// Initializes the specified sextant. + /// + /// The sextant. + public static void Initialize(this Sextant sextant) + { + if (sextant is null) + { + throw new ArgumentNullException(nameof(sextant)); + } + + sextant.MutableLocator.RegisterViewStackService(); + } + } +} diff --git a/src/Sextant/Sextant.csproj b/src/Sextant/Sextant.csproj index 43dbf90b..5e01827e 100644 --- a/src/Sextant/Sextant.csproj +++ b/src/Sextant/Sextant.csproj @@ -1,6 +1,6 @@  - netstandard2.0;Xamarin.iOS10;Xamarin.TVOS10;net5.0 + netstandard2.0;Xamarin.iOS10;Xamarin.TVOS10;net5.0;net6.0;net6.0-android;net6.0-ios;net6.0-tvos;net6.0-macos; $(TargetFrameworks);net461;net472;uap10.0.16299 Sextant Sextant @@ -23,6 +23,12 @@ + + + + + + @@ -37,13 +43,28 @@ - + + + + + + + + + + + + + + + + @@ -57,8 +78,7 @@ - + - From ab6e1362ec63224812651c373a218853c72eae8b Mon Sep 17 00:00:00 2001 From: OmnipotentOwl <1769881+OmnipotentOwl@users.noreply.github.com> Date: Thu, 16 Dec 2021 18:10:17 -0500 Subject: [PATCH 05/41] Update samples for sextant to use newer nuget versions --- .../SextantSample.Android.csproj | 30 +++ .../SextantSample.ViewModels.csproj | 3 +- Sample/SextantSample.Maui/App.xaml | 27 +++ Sample/SextantSample.Maui/App.xaml.cs | 30 +++ Sample/SextantSample.Maui/GlobalUsings.cs | 16 ++ Sample/SextantSample.Maui/MauiProgram.cs | 45 +++++ .../Platforms/Android/AndroidManifest.xml | 6 + .../Platforms/Android/MainActivity.cs | 24 +++ .../Platforms/Android/MainApplication.cs | 18 ++ .../Android/Resources/values/colors.xml | 6 + .../Platforms/MacCatalyst/AppDelegate.cs | 11 ++ .../Platforms/MacCatalyst/Info.plist | 30 +++ .../Platforms/MacCatalyst/Program.cs | 15 ++ .../Platforms/Windows/App.xaml | 8 + .../Platforms/Windows/App.xaml.cs | 33 ++++ .../Platforms/Windows/Package.appxmanifest | 58 ++++++ .../Platforms/Windows/app.manifest | 15 ++ .../Platforms/iOS/AppDelegate.cs | 11 ++ .../Platforms/iOS/Info.plist | 34 ++++ .../Platforms/iOS/Program.cs | 15 ++ .../Platforms/iOS/Resources/LaunchScreen.xib | 43 +++++ .../Properties/launchSettings.json | 8 + .../Resources/Fonts/OpenSans-Regular.ttf | 3 + .../Resources/Images/dotnet_bot.svg | 93 +++++++++ .../SextantSample.Maui/Resources/appicon.svg | 4 + .../Resources/appiconfg.svg | 8 + .../SextantSample.Maui.csproj | 77 ++++++++ .../Views/BlueNavigationView.cs | 20 ++ .../Views/FirstModalView.xaml | 15 ++ .../Views/FirstModalView.xaml.cs | 33 ++++ .../SextantSample.Maui/Views/GreenView.xaml | 15 ++ .../Views/GreenView.xaml.cs | 18 ++ Sample/SextantSample.Maui/Views/HomeView.xaml | 16 ++ .../SextantSample.Maui/Views/HomeView.xaml.cs | 30 +++ Sample/SextantSample.Maui/Views/RedView.xaml | 17 ++ .../SextantSample.Maui/Views/RedView.xaml.cs | 26 +++ .../Views/SecondModalView.xaml | 15 ++ .../Views/SecondModalView.xaml.cs | 24 +++ .../SextantSample.iOS.csproj | 46 ++++- Sample/SextantSample.sln | 180 +++++++++++++++++- Sample/SextantSample/SextantSample.csproj | 1 + 41 files changed, 1121 insertions(+), 6 deletions(-) create mode 100644 Sample/SextantSample.Maui/App.xaml create mode 100644 Sample/SextantSample.Maui/App.xaml.cs create mode 100644 Sample/SextantSample.Maui/GlobalUsings.cs create mode 100644 Sample/SextantSample.Maui/MauiProgram.cs create mode 100644 Sample/SextantSample.Maui/Platforms/Android/AndroidManifest.xml create mode 100644 Sample/SextantSample.Maui/Platforms/Android/MainActivity.cs create mode 100644 Sample/SextantSample.Maui/Platforms/Android/MainApplication.cs create mode 100644 Sample/SextantSample.Maui/Platforms/Android/Resources/values/colors.xml create mode 100644 Sample/SextantSample.Maui/Platforms/MacCatalyst/AppDelegate.cs create mode 100644 Sample/SextantSample.Maui/Platforms/MacCatalyst/Info.plist create mode 100644 Sample/SextantSample.Maui/Platforms/MacCatalyst/Program.cs create mode 100644 Sample/SextantSample.Maui/Platforms/Windows/App.xaml create mode 100644 Sample/SextantSample.Maui/Platforms/Windows/App.xaml.cs create mode 100644 Sample/SextantSample.Maui/Platforms/Windows/Package.appxmanifest create mode 100644 Sample/SextantSample.Maui/Platforms/Windows/app.manifest create mode 100644 Sample/SextantSample.Maui/Platforms/iOS/AppDelegate.cs create mode 100644 Sample/SextantSample.Maui/Platforms/iOS/Info.plist create mode 100644 Sample/SextantSample.Maui/Platforms/iOS/Program.cs create mode 100644 Sample/SextantSample.Maui/Platforms/iOS/Resources/LaunchScreen.xib create mode 100644 Sample/SextantSample.Maui/Properties/launchSettings.json create mode 100644 Sample/SextantSample.Maui/Resources/Fonts/OpenSans-Regular.ttf create mode 100644 Sample/SextantSample.Maui/Resources/Images/dotnet_bot.svg create mode 100644 Sample/SextantSample.Maui/Resources/appicon.svg create mode 100644 Sample/SextantSample.Maui/Resources/appiconfg.svg create mode 100644 Sample/SextantSample.Maui/SextantSample.Maui.csproj create mode 100644 Sample/SextantSample.Maui/Views/BlueNavigationView.cs create mode 100644 Sample/SextantSample.Maui/Views/FirstModalView.xaml create mode 100644 Sample/SextantSample.Maui/Views/FirstModalView.xaml.cs create mode 100644 Sample/SextantSample.Maui/Views/GreenView.xaml create mode 100644 Sample/SextantSample.Maui/Views/GreenView.xaml.cs create mode 100644 Sample/SextantSample.Maui/Views/HomeView.xaml create mode 100644 Sample/SextantSample.Maui/Views/HomeView.xaml.cs create mode 100644 Sample/SextantSample.Maui/Views/RedView.xaml create mode 100644 Sample/SextantSample.Maui/Views/RedView.xaml.cs create mode 100644 Sample/SextantSample.Maui/Views/SecondModalView.xaml create mode 100644 Sample/SextantSample.Maui/Views/SecondModalView.xaml.cs diff --git a/Sample/SextantSample.Android/SextantSample.Android.csproj b/Sample/SextantSample.Android/SextantSample.Android.csproj index b9181802..05dcf69b 100644 --- a/Sample/SextantSample.Android/SextantSample.Android.csproj +++ b/Sample/SextantSample.Android/SextantSample.Android.csproj @@ -58,6 +58,36 @@ true armeabi-v7a + + true + bin\x64\Debug\ + DEBUG;LOGGING + portable + x64 + Off + 8.0 + prompt + + + true + bin\x64\Release\ + true + portable + x64 + Off + 8.0 + prompt + + + true + bin\x64\Sample Release\ + true + portable + x64 + Off + 8.0 + prompt + diff --git a/Sample/SextantSample.Core/SextantSample.ViewModels.csproj b/Sample/SextantSample.Core/SextantSample.ViewModels.csproj index 97d13568..02a91748 100644 --- a/Sample/SextantSample.Core/SextantSample.ViewModels.csproj +++ b/Sample/SextantSample.Core/SextantSample.ViewModels.csproj @@ -1,7 +1,8 @@ - netstandard2.0 + netstandard2.0;net6.0 + AnyCPU;x64 diff --git a/Sample/SextantSample.Maui/App.xaml b/Sample/SextantSample.Maui/App.xaml new file mode 100644 index 00000000..0a0639a6 --- /dev/null +++ b/Sample/SextantSample.Maui/App.xaml @@ -0,0 +1,27 @@ + + + + + #512bdf + White + + + + + + + + diff --git a/Sample/SextantSample.Maui/App.xaml.cs b/Sample/SextantSample.Maui/App.xaml.cs new file mode 100644 index 00000000..a9b56218 --- /dev/null +++ b/Sample/SextantSample.Maui/App.xaml.cs @@ -0,0 +1,30 @@ +using System; +using Microsoft.Maui; +using Microsoft.Maui.Controls; +using Microsoft.Maui.Controls.PlatformConfiguration.WindowsSpecific; +using Microsoft.Maui.Controls.Xaml; +using Sextant; +using Sextant.Maui; +using SextantSample.ViewModels; +using Splat; + +[assembly: XamlCompilation(XamlCompilationOptions.Compile)] + +namespace SextantSample.Maui +{ + public partial class App : Application + { + public App() + { + InitializeComponent(); + + Locator + .Current + .GetService() + .PushPage(new HomeViewModel(), null, true, false) + .Subscribe(); + + MainPage = Locator.Current.GetNavigationView(); + } + } +} diff --git a/Sample/SextantSample.Maui/GlobalUsings.cs b/Sample/SextantSample.Maui/GlobalUsings.cs new file mode 100644 index 00000000..e6f3de42 --- /dev/null +++ b/Sample/SextantSample.Maui/GlobalUsings.cs @@ -0,0 +1,16 @@ +global using Microsoft.Maui.Essentials; +global using Microsoft.Maui; +global using Microsoft.Maui.Controls; +global using Microsoft.Maui.Controls.Hosting; +global using Microsoft.Maui.Hosting; +global using Microsoft.Maui.LifecycleEvents; + +global using System; +global using System.Diagnostics; +global using System.Threading.Tasks; +global using System.Collections.Generic; + +global using ReactiveUI; +global using ReactiveUI.Maui; + +global using Application = Microsoft.Maui.Controls.Application; diff --git a/Sample/SextantSample.Maui/MauiProgram.cs b/Sample/SextantSample.Maui/MauiProgram.cs new file mode 100644 index 00000000..0eef77fb --- /dev/null +++ b/Sample/SextantSample.Maui/MauiProgram.cs @@ -0,0 +1,45 @@ +using Microsoft.Maui; +using Microsoft.Maui.Controls.Compatibility; +using Microsoft.Maui.Controls.Hosting; +using Microsoft.Maui.Hosting; +using ReactiveUI; +using Sextant; +using Sextant.Maui; +using SextantSample.Maui.Views; +using SextantSample.ViewModels; +using Splat; +using static Sextant.Sextant; + +namespace SextantSample.Maui +{ + public static class MauiProgram + { + public static MauiApp CreateMauiApp() + { + var builder = MauiApp.CreateBuilder(); + builder + .UseMauiApp() + .ConfigureFonts(fonts => + { + fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); + }); + + RxApp.DefaultExceptionHandler = new SextantDefaultExceptionHandler(); + var resolver = Locator.CurrentMutable; + resolver.InitializeSplat(); + resolver.InitializeReactiveUI(); + Instance.InitializeMaui(); + Locator + .CurrentMutable + .RegisterView() + .RegisterView() + .RegisterView() + .RegisterView() + .RegisterView() + .RegisterNavigationView(() => new BlueNavigationView()) + .RegisterViewModel(() => new GreenViewModel(Locator.Current.GetService())); + + return builder.Build(); + } + } +} diff --git a/Sample/SextantSample.Maui/Platforms/Android/AndroidManifest.xml b/Sample/SextantSample.Maui/Platforms/Android/AndroidManifest.xml new file mode 100644 index 00000000..7570ff62 --- /dev/null +++ b/Sample/SextantSample.Maui/Platforms/Android/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Sample/SextantSample.Maui/Platforms/Android/MainActivity.cs b/Sample/SextantSample.Maui/Platforms/Android/MainActivity.cs new file mode 100644 index 00000000..622f4ba7 --- /dev/null +++ b/Sample/SextantSample.Maui/Platforms/Android/MainActivity.cs @@ -0,0 +1,24 @@ +using Android.App; +using Android.Content.PM; +using Android.OS; +using Microsoft.Maui; + +namespace SextantSample.Maui +{ + [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize)] + public class MainActivity : MauiAppCompatActivity + { + protected override void OnCreate(Bundle savedInstanceState) + { + base.OnCreate(savedInstanceState); + Platform.Init(this, savedInstanceState); + } + + public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults) + { + Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults); + + base.OnRequestPermissionsResult(requestCode, permissions, grantResults); + } + } +} diff --git a/Sample/SextantSample.Maui/Platforms/Android/MainApplication.cs b/Sample/SextantSample.Maui/Platforms/Android/MainApplication.cs new file mode 100644 index 00000000..1f58769b --- /dev/null +++ b/Sample/SextantSample.Maui/Platforms/Android/MainApplication.cs @@ -0,0 +1,18 @@ +using Android.App; +using Android.Runtime; +using Microsoft.Maui; +using System; + +namespace SextantSample.Maui +{ + [Application] + public class MainApplication : MauiApplication + { + public MainApplication(IntPtr handle, JniHandleOwnership ownership) + : base(handle, ownership) + { + } + + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); + } +} \ No newline at end of file diff --git a/Sample/SextantSample.Maui/Platforms/Android/Resources/values/colors.xml b/Sample/SextantSample.Maui/Platforms/Android/Resources/values/colors.xml new file mode 100644 index 00000000..c04d7492 --- /dev/null +++ b/Sample/SextantSample.Maui/Platforms/Android/Resources/values/colors.xml @@ -0,0 +1,6 @@ + + + #512BD4 + #2B0B98 + #2B0B98 + \ No newline at end of file diff --git a/Sample/SextantSample.Maui/Platforms/MacCatalyst/AppDelegate.cs b/Sample/SextantSample.Maui/Platforms/MacCatalyst/AppDelegate.cs new file mode 100644 index 00000000..b61f86f8 --- /dev/null +++ b/Sample/SextantSample.Maui/Platforms/MacCatalyst/AppDelegate.cs @@ -0,0 +1,11 @@ +using Foundation; +using Microsoft.Maui; + +namespace SextantSample.Maui +{ + [Register("AppDelegate")] + public class AppDelegate : MauiUIApplicationDelegate + { + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); + } +} \ No newline at end of file diff --git a/Sample/SextantSample.Maui/Platforms/MacCatalyst/Info.plist b/Sample/SextantSample.Maui/Platforms/MacCatalyst/Info.plist new file mode 100644 index 00000000..c96dd0a2 --- /dev/null +++ b/Sample/SextantSample.Maui/Platforms/MacCatalyst/Info.plist @@ -0,0 +1,30 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/appicon.appiconset + + diff --git a/Sample/SextantSample.Maui/Platforms/MacCatalyst/Program.cs b/Sample/SextantSample.Maui/Platforms/MacCatalyst/Program.cs new file mode 100644 index 00000000..ee3165bb --- /dev/null +++ b/Sample/SextantSample.Maui/Platforms/MacCatalyst/Program.cs @@ -0,0 +1,15 @@ +using UIKit; + +namespace SextantSample.Maui +{ + public class Program + { + // This is the main entry point of the application. + static void Main(string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main(args, null, typeof(AppDelegate)); + } + } +} \ No newline at end of file diff --git a/Sample/SextantSample.Maui/Platforms/Windows/App.xaml b/Sample/SextantSample.Maui/Platforms/Windows/App.xaml new file mode 100644 index 00000000..19d4aee7 --- /dev/null +++ b/Sample/SextantSample.Maui/Platforms/Windows/App.xaml @@ -0,0 +1,8 @@ + + + diff --git a/Sample/SextantSample.Maui/Platforms/Windows/App.xaml.cs b/Sample/SextantSample.Maui/Platforms/Windows/App.xaml.cs new file mode 100644 index 00000000..9c1fb085 --- /dev/null +++ b/Sample/SextantSample.Maui/Platforms/Windows/App.xaml.cs @@ -0,0 +1,33 @@ +using Microsoft.Maui; +using Microsoft.UI.Xaml; +using Windows.ApplicationModel; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace SextantSample.Maui.WinUI +{ + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + public partial class App : MauiWinUIApplication + { + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + public App() + { + this.InitializeComponent(); + } + + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); + + protected override void OnLaunched(LaunchActivatedEventArgs args) + { + base.OnLaunched(args); + + Microsoft.Maui.Essentials.Platform.OnLaunched(args); + } + } +} diff --git a/Sample/SextantSample.Maui/Platforms/Windows/Package.appxmanifest b/Sample/SextantSample.Maui/Platforms/Windows/Package.appxmanifest new file mode 100644 index 00000000..b69fb05e --- /dev/null +++ b/Sample/SextantSample.Maui/Platforms/Windows/Package.appxmanifest @@ -0,0 +1,58 @@ + + + + + + + + SextantSample.Maui + Microsoft + Assets\appiconStoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample/SextantSample.Maui/Platforms/Windows/app.manifest b/Sample/SextantSample.Maui/Platforms/Windows/app.manifest new file mode 100644 index 00000000..380448ab --- /dev/null +++ b/Sample/SextantSample.Maui/Platforms/Windows/app.manifest @@ -0,0 +1,15 @@ + + + + + + + + true/PM + PerMonitorV2, PerMonitor + + + diff --git a/Sample/SextantSample.Maui/Platforms/iOS/AppDelegate.cs b/Sample/SextantSample.Maui/Platforms/iOS/AppDelegate.cs new file mode 100644 index 00000000..b61f86f8 --- /dev/null +++ b/Sample/SextantSample.Maui/Platforms/iOS/AppDelegate.cs @@ -0,0 +1,11 @@ +using Foundation; +using Microsoft.Maui; + +namespace SextantSample.Maui +{ + [Register("AppDelegate")] + public class AppDelegate : MauiUIApplicationDelegate + { + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); + } +} \ No newline at end of file diff --git a/Sample/SextantSample.Maui/Platforms/iOS/Info.plist b/Sample/SextantSample.Maui/Platforms/iOS/Info.plist new file mode 100644 index 00000000..ed2ffb61 --- /dev/null +++ b/Sample/SextantSample.Maui/Platforms/iOS/Info.plist @@ -0,0 +1,34 @@ + + + + + LSRequiresIPhoneOS + + MinimumOSVersion + 10.3.4 + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/appicon.appiconset + + diff --git a/Sample/SextantSample.Maui/Platforms/iOS/Program.cs b/Sample/SextantSample.Maui/Platforms/iOS/Program.cs new file mode 100644 index 00000000..ee3165bb --- /dev/null +++ b/Sample/SextantSample.Maui/Platforms/iOS/Program.cs @@ -0,0 +1,15 @@ +using UIKit; + +namespace SextantSample.Maui +{ + public class Program + { + // This is the main entry point of the application. + static void Main(string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main(args, null, typeof(AppDelegate)); + } + } +} \ No newline at end of file diff --git a/Sample/SextantSample.Maui/Platforms/iOS/Resources/LaunchScreen.xib b/Sample/SextantSample.Maui/Platforms/iOS/Resources/LaunchScreen.xib new file mode 100644 index 00000000..3e5075f7 --- /dev/null +++ b/Sample/SextantSample.Maui/Platforms/iOS/Resources/LaunchScreen.xib @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample/SextantSample.Maui/Properties/launchSettings.json b/Sample/SextantSample.Maui/Properties/launchSettings.json new file mode 100644 index 00000000..edf8aadc --- /dev/null +++ b/Sample/SextantSample.Maui/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Windows Machine": { + "commandName": "MsixPackage", + "nativeDebugging": false + } + } +} \ No newline at end of file diff --git a/Sample/SextantSample.Maui/Resources/Fonts/OpenSans-Regular.ttf b/Sample/SextantSample.Maui/Resources/Fonts/OpenSans-Regular.ttf new file mode 100644 index 00000000..1beddae5 --- /dev/null +++ b/Sample/SextantSample.Maui/Resources/Fonts/OpenSans-Regular.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:037236ed4bf58a85f67074c165d308260fd6be01c86d7df4e79ea16eb273f8c5 +size 96932 diff --git a/Sample/SextantSample.Maui/Resources/Images/dotnet_bot.svg b/Sample/SextantSample.Maui/Resources/Images/dotnet_bot.svg new file mode 100644 index 00000000..abfaff26 --- /dev/null +++ b/Sample/SextantSample.Maui/Resources/Images/dotnet_bot.svg @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample/SextantSample.Maui/Resources/appicon.svg b/Sample/SextantSample.Maui/Resources/appicon.svg new file mode 100644 index 00000000..9d63b651 --- /dev/null +++ b/Sample/SextantSample.Maui/Resources/appicon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Sample/SextantSample.Maui/Resources/appiconfg.svg b/Sample/SextantSample.Maui/Resources/appiconfg.svg new file mode 100644 index 00000000..21dfb25f --- /dev/null +++ b/Sample/SextantSample.Maui/Resources/appiconfg.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Sample/SextantSample.Maui/SextantSample.Maui.csproj b/Sample/SextantSample.Maui/SextantSample.Maui.csproj new file mode 100644 index 00000000..007d4ecd --- /dev/null +++ b/Sample/SextantSample.Maui/SextantSample.Maui.csproj @@ -0,0 +1,77 @@ + + + + net6.0-ios;net6.0-android;net6.0-maccatalyst + $(TargetFrameworks);net6.0-windows10.0.19041 + Exe + SextantSample.Maui + true + true + true + + + SextantSample.Maui + + + com.companyname.SextantSample.Maui + + + 1 + + + True + + 14.2 + 14.0 + 21.0 + 10.0.17763.0 + 10.0.17763.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %(Filename) + + + + + + Designer + + + + + WinExe + win10-x64 + MSIX + + + diff --git a/Sample/SextantSample.Maui/Views/BlueNavigationView.cs b/Sample/SextantSample.Maui/Views/BlueNavigationView.cs new file mode 100644 index 00000000..b7dadee0 --- /dev/null +++ b/Sample/SextantSample.Maui/Views/BlueNavigationView.cs @@ -0,0 +1,20 @@ +using Microsoft.Maui.Graphics; +using ReactiveUI; +using Sextant.Maui; + +namespace SextantSample.Maui.Views +{ + public class BlueNavigationView : NavigationView, IViewFor + { + public BlueNavigationView() + : base(RxApp.MainThreadScheduler, RxApp.TaskpoolScheduler, ViewLocator.Current) + { + BarBackgroundColor = Colors.Blue; + BarTextColor = Colors.White; + } + +#pragma warning disable CA1065 // Do not raise exceptions in unexpected locations + public object ViewModel { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } +#pragma warning restore CA1065 // Do not raise exceptions in unexpected locations + } +} diff --git a/Sample/SextantSample.Maui/Views/FirstModalView.xaml b/Sample/SextantSample.Maui/Views/FirstModalView.xaml new file mode 100644 index 00000000..e37b83ee --- /dev/null +++ b/Sample/SextantSample.Maui/Views/FirstModalView.xaml @@ -0,0 +1,15 @@ + + + + +