From a1ba7afb19fabb18b04ddbee25e1d110e41a8c4e Mon Sep 17 00:00:00 2001
From: OmnipotentOwl <1769881+OmnipotentOwl@users.noreply.github.com>
Date: Sat, 9 Dec 2023 16:05:13 -0500
Subject: [PATCH] Feature: Add MAUI support (#691)
---
.github/workflows/build-samples.yml | 44 +-
.github/workflows/ci-build.yml | 134 +--
.github/workflows/release.yml | 25 +
.../Properties/AndroidManifest.xml | 4 +-
.../Resources/values/styles.xml | 4 +-
.../SextantSample.Android.csproj | 33 +-
.../SextantSample.ViewModels.csproj | 3 +-
Sample/SextantSample.Maui/App.xaml | 11 +
Sample/SextantSample.Maui/App.xaml.cs | 20 +
Sample/SextantSample.Maui/GlobalUsings.cs | 17 +
Sample/SextantSample.Maui/MauiProgram.cs | 40 +
.../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 | 26 +
.../Platforms/Windows/Package.appxmanifest | 56 ++
.../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/AppIcon/appicon.svg | 4 +
.../Resources/AppIcon/appiconfg.svg | 8 +
.../Resources/Fonts/OpenSans-Regular.ttf | 3 +
.../Resources/Fonts/OpenSans-Semibold.ttf | 3 +
.../Resources/Images/dotnet_bot.svg | 93 ++
.../Resources/Raw/AboutAssets.txt | 15 +
.../Resources/Splash/splash.svg | 8 +
.../Resources/Styles/Colors.xaml | 44 +
.../Resources/Styles/Styles.xaml | 405 +++++++++
.../SextantSample.Maui.csproj | 112 +++
.../Views/BlueNavigationView.cs | 16 +
.../Views/FirstModalView.xaml | 15 +
.../Views/FirstModalView.xaml.cs | 30 +
.../SextantSample.Maui/Views/GreenView.xaml | 15 +
.../Views/GreenView.xaml.cs | 13 +
Sample/SextantSample.Maui/Views/HomeView.xaml | 16 +
.../SextantSample.Maui/Views/HomeView.xaml.cs | 27 +
Sample/SextantSample.Maui/Views/RedView.xaml | 17 +
.../SextantSample.Maui/Views/RedView.xaml.cs | 22 +
.../Views/SecondModalView.xaml | 15 +
.../Views/SecondModalView.xaml.cs | 20 +
.../SextantSample.iOS.csproj | 44 +-
Sample/SextantSample.sln | 180 +++-
Sample/SextantSample/SextantSample.csproj | 3 +-
Sample/global.json | 5 +
src/Directory.build.props | 45 +-
src/Directory.build.targets | 62 +-
src/Sextant.Avalonia/Sextant.Avalonia.csproj | 2 +-
src/Sextant.Maui/Behaviors/BehaviorBase.cs | 66 ++
.../NavigationPageSystemPopBehavior.cs | 70 ++
src/Sextant.Maui/GlobalUsings.cs | 9 +
.../Mixins/DependencyResolverMixins.cs | 105 +++
src/Sextant.Maui/Mixins/SextantExtensions.cs | 32 +
src/Sextant.Maui/NavigationSource.cs | 23 +
src/Sextant.Maui/NavigationView.cs | 225 +++++
src/Sextant.Maui/Sextant.Maui.csproj | 32 +
src/Sextant.Mocks/Sextant.Mocks.csproj | 4 +-
...antPluginsPopup.netcoreapp3.1.approved.txt | 67 --
.../API/ApiApprovalTests.cs | 87 --
src/Sextant.Plugins.Popup.Tests/PopupMock.cs | 14 -
.../PopupNavigationMock.cs | 79 --
.../PopupViewStackServiceFixture.cs | 53 --
.../PopupViewStackServiceTests.cs | 854 ------------------
.../Sextant.Plugins.Popup.Tests.csproj | 28 -
...rovalTests.Sextant.DotNet6_0.verified.txt} | 9 +-
...rovalTests.Sextant.DotNet7_0.verified.txt} | 9 +-
...provalTests.Sextant.DotNet8_0.verified.txt | 196 ++++
src/Sextant.Tests/API/ApiApprovalTests.cs | 71 +-
src/Sextant.Tests/API/ApiExtensions.cs | 45 +
src/Sextant.Tests/Sextant.Tests.csproj | 10 +-
...lTests.SextantXamForms.net6.0.approved.txt | 51 ++
.../Sextant.XamForms.Tests.csproj | 9 +-
src/Sextant.XamForms/Sextant.XamForms.csproj | 6 +-
.../Sextant.iOS.Runner.csproj | 8 +-
src/Sextant.sln | 16 +-
.../{net5 => android}/SextantExtensions.cs | 0
.../Platforms/mac/SextantExtensions.cs | 33 +
.../Platforms/net/SextantExtensions.cs | 29 +
.../uikit-common/NavigationViewController.cs | 2 +
src/Sextant/Sextant.csproj | 55 +-
src/Sextant/Sextant.csproj.DotSettings | 1 +
.../ViewModelFactoryNotFoundException.cs | 3 +
src/global.json | 5 +
90 files changed, 2740 insertions(+), 1469 deletions(-)
create mode 100644 .github/workflows/release.yml
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/AppIcon/appicon.svg
create mode 100644 Sample/SextantSample.Maui/Resources/AppIcon/appiconfg.svg
create mode 100644 Sample/SextantSample.Maui/Resources/Fonts/OpenSans-Regular.ttf
create mode 100644 Sample/SextantSample.Maui/Resources/Fonts/OpenSans-Semibold.ttf
create mode 100644 Sample/SextantSample.Maui/Resources/Images/dotnet_bot.svg
create mode 100644 Sample/SextantSample.Maui/Resources/Raw/AboutAssets.txt
create mode 100644 Sample/SextantSample.Maui/Resources/Splash/splash.svg
create mode 100644 Sample/SextantSample.Maui/Resources/Styles/Colors.xaml
create mode 100644 Sample/SextantSample.Maui/Resources/Styles/Styles.xaml
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
create mode 100644 Sample/global.json
create mode 100644 src/Sextant.Maui/Behaviors/BehaviorBase.cs
create mode 100644 src/Sextant.Maui/Behaviors/NavigationPageSystemPopBehavior.cs
create mode 100644 src/Sextant.Maui/GlobalUsings.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
delete mode 100644 src/Sextant.Plugins.Popup.Tests/API/ApiApprovalTests.SextantPluginsPopup.netcoreapp3.1.approved.txt
delete mode 100644 src/Sextant.Plugins.Popup.Tests/API/ApiApprovalTests.cs
delete mode 100644 src/Sextant.Plugins.Popup.Tests/PopupMock.cs
delete mode 100644 src/Sextant.Plugins.Popup.Tests/PopupNavigationMock.cs
delete mode 100644 src/Sextant.Plugins.Popup.Tests/PopupViewStackServiceFixture.cs
delete mode 100644 src/Sextant.Plugins.Popup.Tests/PopupViewStackServiceTests.cs
delete mode 100644 src/Sextant.Plugins.Popup.Tests/Sextant.Plugins.Popup.Tests.csproj
rename src/Sextant.Tests/API/{ApiApprovalTests.Sextant.net5.0.approved.txt => ApiApprovalTests.Sextant.DotNet6_0.verified.txt} (97%)
rename src/Sextant.Tests/API/{ApiApprovalTests.Sextant.netcoreapp3.1.approved.txt => ApiApprovalTests.Sextant.DotNet7_0.verified.txt} (97%)
create mode 100644 src/Sextant.Tests/API/ApiApprovalTests.Sextant.DotNet8_0.verified.txt
create mode 100644 src/Sextant.Tests/API/ApiExtensions.cs
create mode 100644 src/Sextant.XamForms.Tests/API/ApiApprovalTests.SextantXamForms.net6.0.approved.txt
rename src/Sextant/Platforms/{net5 => android}/SextantExtensions.cs (100%)
create mode 100644 src/Sextant/Platforms/mac/SextantExtensions.cs
create mode 100644 src/Sextant/Platforms/net/SextantExtensions.cs
diff --git a/.github/workflows/build-samples.yml b/.github/workflows/build-samples.yml
index 30c596a7..8c6befea 100644
--- a/.github/workflows/build-samples.yml
+++ b/.github/workflows/build-samples.yml
@@ -5,6 +5,7 @@ on:
branches: [ main ]
pull_request:
branches: [ main ]
+ workflow_dispatch:
jobs:
build-samples:
@@ -12,25 +13,50 @@ jobs:
matrix:
configuration: [Debug, Release]
- runs-on: windows-latest
+ runs-on: windows-2022
steps:
+ - 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: Setup Java JDK
+ uses: actions/setup-java@v4.0.0
+ with:
+ distribution: 'microsoft'
+ java-version: '11'
+
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
lfs: true
- # Install the .NET Core workload
- - name: Install .NET Core 3.1.x
- uses: actions/setup-dotnet@v1
+ # Install the .NET workload
+ - name: Setup .NET 6/7/8
+ uses: actions/setup-dotnet@v3
with:
- dotnet-version: 3.1.x
+ dotnet-version: |
+ 6.0.x
+ 7.0.x
+ 8.0.x
- - name: Install .NET 5.0.x
- uses: actions/setup-dotnet@v1
- with:
- dotnet-version: 5.0.x
+ - 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
# Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
- name: Setup MSBuild.exe
diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml
index 984c4177..75b9451d 100644
--- a/.github/workflows/ci-build.yml
+++ b/.github/workflows/ci-build.yml
@@ -4,130 +4,22 @@ on:
push:
branches: [ main ]
pull_request:
- types: [opened, synchronize, reopened, closed]
branches: [ main ]
-
+
env:
- configuration: Release
productNamespacePrefix: "Sextant"
+permissions:
+ contents: read
+
jobs:
build:
- runs-on: windows-latest
- outputs:
- nbgv: ${{ steps.nbgv.outputs.SemVer2 }}
- steps:
- - name: Checkout
- uses: actions/checkout@v2
- with:
- fetch-depth: 0
- lfs: true
-
- - name: Install .NET Core 3.1.x
- uses: actions/setup-dotnet@v1
- with:
- dotnet-version: 3.1.x
-
- - name: Install .NET 5.0.x
- uses: actions/setup-dotnet@v1
- with:
- dotnet-version: 5.0.x
-
- - name: Add MSBuild to PATH
- uses: glennawatson/setup-msbuild@v1.0.3
-
- # - name: Update VS2019
- # shell: powershell
- # run: Start-Process -Wait -PassThru -FilePath "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installer.exe" -ArgumentList "update --passive --norestart --installpath ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise"""
-
- - name: NBGV
- id: nbgv
- uses: dotnet/nbgv@master
- with:
- setAllVars: true
-
- - name: NuGet Restore
- run: dotnet restore
- working-directory: src
-
- - name: Build
- run: msbuild /t:build,pack /p:NoPackageAnalysis=true /verbosity:minimal /p:Configuration=${{ env.configuration }}
- working-directory: src
-
- - name: Run Unit Tests and Generate Coverage
- uses: glennawatson/coverlet-msbuild@v1
- with:
- project-files: '**/*Tests*.csproj'
- no-build: true
- exclude-filter: '[${{env.productNamespacePrefix}}.*.Tests.*]*'
- include-filter: '[${{env.productNamespacePrefix}}*]*'
- output-format: cobertura
- output: '../../artifacts/'
- configuration: ${{ env.configuration }}
-
- - name: Upload Code Coverage
- shell: bash
- run: |
- echo $PWD
- bash <(curl -s https://codecov.io/bash) -X gcov -X coveragepy -t ${{ env.CODECOV_TOKEN }} -s '$PWD/artifacts' -f '*.xml'
- env:
- CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
-
- - name: Create NuGet Artifacts
- uses: actions/upload-artifact@master
- with:
- name: nuget
- path: '**/*.nupkg'
-
- release:
- runs-on: ubuntu-latest
- needs: build
- if: contains(github.event.pull_request.labels.*.name, 'release') && github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged == true
- steps:
- - name: Checkout
- uses: actions/checkout@v2
- with:
- fetch-depth: 0
-
- - name: Download NuGet Packages
- uses: actions/download-artifact@v2
- with:
- name: nuget
-
- - name: Save SignClient Configuration
- run: 'echo "$SIGN_CLIENT_CONFIG" > SignPackages.json'
- shell: bash
- env:
- SIGN_CLIENT_CONFIG: ${{secrets.SIGN_CLIENT_CONFIG}}
-
- - name: Sign NuGet Packages
- uses: glennawatson/signclient@v1
- with:
- input-files: '**/*.nupkg'
- sign-client-secret: ${{ secrets.SIGN_CLIENT_SECRET }}
- sign-client-user: ${{ secrets.SIGN_CLIENT_USER_ID }}
- project-name: reactiveui
- description: reactiveui
- config-file: SignPackages.json
-
- - name: Changelog
- uses: glennawatson/ChangeLog@v1
- id: changelog
-
- - name: Create Release
- uses: actions/create-release@v1
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
- with:
- tag_name: ${{ needs.build.outputs.nbgv }}
- release_name: ${{ needs.build.outputs.nbgv }}
- body: |
- ${{ steps.changelog.outputs.commitLog }}
-
- - name: NuGet Push
- env:
- NUGET_AUTH_TOKEN: ${{ secrets.NUGET_API_KEY }}
- SOURCE_URL: https://api.nuget.org/v3/index.json
- run: |
- dotnet nuget push -s ${{ env.SOURCE_URL }} -k ${{ env.NUGET_AUTH_TOKEN }} **/*.nupkg
-
+ permissions:
+ contents: none
+ uses: reactiveui/actions-common/.github/workflows/workflow-common-setup-and-build.yml@main
+ with:
+ configuration: Release
+ productNamespacePrefix: "Sextant"
+ useVisualStudioPreview: false
+ useMauiCheckDotNetTool: false
+ solutionFile: "Sextant.sln"
\ No newline at end of file
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 00000000..f42547f5
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,25 @@
+name: Release
+
+on:
+ push:
+ branches:
+ - main
+ - patches/*
+
+env:
+ productNamespacePrefix: "Sextant"
+
+jobs:
+ release:
+ uses: reactiveui/actions-common/.github/workflows/workflow-common-release.yml@main
+ with:
+ configuration: Release
+ productNamespacePrefix: "Sextant"
+ useVisualStudioPreview: true
+ useMauiCheckDotNetTool: false
+ solutionFile: "Sextant.sln"
+ secrets:
+ SIGN_CLIENT_USER_ID: ${{ secrets.SIGN_CLIENT_USER_ID }}
+ SIGN_CLIENT_SECRET: ${{ secrets.SIGN_CLIENT_SECRET }}
+ SIGN_CLIENT_CONFIG: ${{ secrets.SIGN_CLIENT_CONFIG }}
+ NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
\ No newline at end of file
diff --git a/Sample/SextantSample.Android/Properties/AndroidManifest.xml b/Sample/SextantSample.Android/Properties/AndroidManifest.xml
index 868b6601..da365097 100644
--- a/Sample/SextantSample.Android/Properties/AndroidManifest.xml
+++ b/Sample/SextantSample.Android/Properties/AndroidManifest.xml
@@ -1,5 +1,5 @@
-
+
-
+
\ No newline at end of file
diff --git a/Sample/SextantSample.Android/Resources/values/styles.xml b/Sample/SextantSample.Android/Resources/values/styles.xml
index b6308586..48d15fe3 100644
--- a/Sample/SextantSample.Android/Resources/values/styles.xml
+++ b/Sample/SextantSample.Android/Resources/values/styles.xml
@@ -4,7 +4,7 @@
-
-
diff --git a/Sample/SextantSample.Android/SextantSample.Android.csproj b/Sample/SextantSample.Android/SextantSample.Android.csproj
index b9181802..b9f25840 100644
--- a/Sample/SextantSample.Android/SextantSample.Android.csproj
+++ b/Sample/SextantSample.Android/SextantSample.Android.csproj
@@ -15,7 +15,7 @@
Properties\AndroidManifest.xml
Resources
Assets
- v10.0
+ v13.0
@@ -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
+
@@ -66,6 +96,7 @@
+
diff --git a/Sample/SextantSample.Core/SextantSample.ViewModels.csproj b/Sample/SextantSample.Core/SextantSample.ViewModels.csproj
index 97d13568..8ca4e604 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;net7.0;net8.0
+ AnyCPU;x64
diff --git a/Sample/SextantSample.Maui/App.xaml b/Sample/SextantSample.Maui/App.xaml
new file mode 100644
index 00000000..28a858fc
--- /dev/null
+++ b/Sample/SextantSample.Maui/App.xaml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/Sample/SextantSample.Maui/App.xaml.cs b/Sample/SextantSample.Maui/App.xaml.cs
new file mode 100644
index 00000000..feed922c
--- /dev/null
+++ b/Sample/SextantSample.Maui/App.xaml.cs
@@ -0,0 +1,20 @@
+[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..0de7e8af
--- /dev/null
+++ b/Sample/SextantSample.Maui/GlobalUsings.cs
@@ -0,0 +1,17 @@
+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 Microsoft.Extensions.Logging;
+global using ReactiveUI;
+global using ReactiveUI.Maui;
+global using Sextant;
+global using Sextant.Maui;
+global using SextantSample.Maui.Views;
+global using SextantSample.ViewModels;
+global using Splat;
+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..decc2c93
--- /dev/null
+++ b/Sample/SextantSample.Maui/MauiProgram.cs
@@ -0,0 +1,40 @@
+using static Sextant.Sextant;
+
+namespace SextantSample.Maui
+{
+ public static class MauiProgram
+ {
+ public static MauiApp CreateMauiApp()
+ {
+ MauiAppBuilder builder = MauiApp.CreateBuilder();
+ builder
+ .UseMauiApp()
+ .ConfigureFonts(fonts =>
+ {
+ fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
+ fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
+ });
+
+ RxApp.DefaultExceptionHandler = new SextantDefaultExceptionHandler();
+ IMutableDependencyResolver 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()));
+
+#if DEBUG
+ builder.Logging.AddDebug();
+#endif
+
+ 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..82163cd6
--- /dev/null
+++ b/Sample/SextantSample.Maui/Platforms/Windows/App.xaml.cs
@@ -0,0 +1,26 @@
+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();
+ }
+}
diff --git a/Sample/SextantSample.Maui/Platforms/Windows/Package.appxmanifest b/Sample/SextantSample.Maui/Platforms/Windows/Package.appxmanifest
new file mode 100644
index 00000000..a04e3629
--- /dev/null
+++ b/Sample/SextantSample.Maui/Platforms/Windows/Package.appxmanifest
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+ $placeholder$
+ User Name
+ $placeholder$.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/AppIcon/appicon.svg b/Sample/SextantSample.Maui/Resources/AppIcon/appicon.svg
new file mode 100644
index 00000000..9d63b651
--- /dev/null
+++ b/Sample/SextantSample.Maui/Resources/AppIcon/appicon.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/Sample/SextantSample.Maui/Resources/AppIcon/appiconfg.svg b/Sample/SextantSample.Maui/Resources/AppIcon/appiconfg.svg
new file mode 100644
index 00000000..21dfb25f
--- /dev/null
+++ b/Sample/SextantSample.Maui/Resources/AppIcon/appiconfg.svg
@@ -0,0 +1,8 @@
+
+
+
\ 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/Fonts/OpenSans-Semibold.ttf b/Sample/SextantSample.Maui/Resources/Fonts/OpenSans-Semibold.ttf
new file mode 100644
index 00000000..d81c625f
--- /dev/null
+++ b/Sample/SextantSample.Maui/Resources/Fonts/OpenSans-Semibold.ttf
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5e8d9e1a89083cd1b0849993fe2f3acc9aa33b7f439f7e8616872f6897f30684
+size 100820
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/Raw/AboutAssets.txt b/Sample/SextantSample.Maui/Resources/Raw/AboutAssets.txt
new file mode 100644
index 00000000..15d62448
--- /dev/null
+++ b/Sample/SextantSample.Maui/Resources/Raw/AboutAssets.txt
@@ -0,0 +1,15 @@
+Any raw assets you want to be deployed with your application can be placed in
+this directory (and child directories). Deployment of the asset to your application
+is automatically handled by the following `MauiAsset` Build Action within your `.csproj`.
+
+
+
+These files will be deployed with you package and will be accessible using Essentials:
+
+ async Task LoadMauiAsset()
+ {
+ using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
+ using var reader = new StreamReader(stream);
+
+ var contents = reader.ReadToEnd();
+ }
diff --git a/Sample/SextantSample.Maui/Resources/Splash/splash.svg b/Sample/SextantSample.Maui/Resources/Splash/splash.svg
new file mode 100644
index 00000000..21dfb25f
--- /dev/null
+++ b/Sample/SextantSample.Maui/Resources/Splash/splash.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/Sample/SextantSample.Maui/Resources/Styles/Colors.xaml b/Sample/SextantSample.Maui/Resources/Styles/Colors.xaml
new file mode 100644
index 00000000..245758ba
--- /dev/null
+++ b/Sample/SextantSample.Maui/Resources/Styles/Colors.xaml
@@ -0,0 +1,44 @@
+
+
+
+
+ #512BD4
+ #DFD8F7
+ #2B0B98
+ White
+ Black
+ #E1E1E1
+ #C8C8C8
+ #ACACAC
+ #919191
+ #6E6E6E
+ #404040
+ #212121
+ #141414
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ #F7B548
+ #FFD590
+ #FFE5B9
+ #28C2D1
+ #7BDDEF
+ #C3F2F4
+ #3E8EED
+ #72ACF1
+ #A7CBF6
+
+
\ No newline at end of file
diff --git a/Sample/SextantSample.Maui/Resources/Styles/Styles.xaml b/Sample/SextantSample.Maui/Resources/Styles/Styles.xaml
new file mode 100644
index 00000000..dc4a0347
--- /dev/null
+++ b/Sample/SextantSample.Maui/Resources/Styles/Styles.xaml
@@ -0,0 +1,405 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Sample/SextantSample.Maui/SextantSample.Maui.csproj b/Sample/SextantSample.Maui/SextantSample.Maui.csproj
new file mode 100644
index 00000000..e328bf52
--- /dev/null
+++ b/Sample/SextantSample.Maui/SextantSample.Maui.csproj
@@ -0,0 +1,112 @@
+
+
+
+ net8.0-ios;net8.0-android;net8.0-maccatalyst
+ $(TargetFrameworks);net8.0-windows10.0.19041.0
+ Exe
+ SextantSample.Maui
+ true
+ true
+ enable
+ true
+
+
+ SextantSample.Maui
+
+
+ com.companyname.SextantSample.Maui
+ 919dc1f9-17a9-48b3-81f8-0b8016bdfbf7
+
+
+ 1.0
+ 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..5a00c440
--- /dev/null
+++ b/Sample/SextantSample.Maui/Views/BlueNavigationView.cs
@@ -0,0 +1,16 @@
+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 @@
+
+
+
+
+
+
+
+
+
diff --git a/Sample/SextantSample.Maui/Views/FirstModalView.xaml.cs b/Sample/SextantSample.Maui/Views/FirstModalView.xaml.cs
new file mode 100644
index 00000000..ca48a26b
--- /dev/null
+++ b/Sample/SextantSample.Maui/Views/FirstModalView.xaml.cs
@@ -0,0 +1,30 @@
+using System.Reactive.Disposables;
+
+namespace SextantSample.Maui.Views
+{
+ public partial class FirstModalView : ReactiveContentPage
+ {
+ public FirstModalView()
+ {
+ InitializeComponent();
+
+ this.WhenActivated(disposables =>
+ {
+ this.BindCommand(ViewModel, vm => vm.OpenModal, v => v.OpenSecondModal)
+ .DisposeWith(disposables);
+ this.BindCommand(ViewModel, vm => vm.PopModal, v => v.PopModal)
+ .DisposeWith(disposables);
+ });
+
+
+
+ Interactions
+ .ErrorMessage
+ .RegisterHandler(async x =>
+ {
+ await DisplayAlert("Error", x.Input.Message, "Done");
+ x.SetOutput(true);
+ });
+ }
+ }
+}
diff --git a/Sample/SextantSample.Maui/Views/GreenView.xaml b/Sample/SextantSample.Maui/Views/GreenView.xaml
new file mode 100644
index 00000000..a4a698ad
--- /dev/null
+++ b/Sample/SextantSample.Maui/Views/GreenView.xaml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/Sample/SextantSample.Maui/Views/GreenView.xaml.cs b/Sample/SextantSample.Maui/Views/GreenView.xaml.cs
new file mode 100644
index 00000000..3ea0510e
--- /dev/null
+++ b/Sample/SextantSample.Maui/Views/GreenView.xaml.cs
@@ -0,0 +1,13 @@
+namespace SextantSample.Maui.Views
+{
+ public partial class GreenView : ReactiveContentPage
+ {
+ public GreenView()
+ {
+ InitializeComponent();
+
+ this.BindCommand(ViewModel, x => x.OpenModal, x => x.Modal);
+ }
+ }
+}
+
diff --git a/Sample/SextantSample.Maui/Views/HomeView.xaml b/Sample/SextantSample.Maui/Views/HomeView.xaml
new file mode 100644
index 00000000..f7f65d34
--- /dev/null
+++ b/Sample/SextantSample.Maui/Views/HomeView.xaml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/Sample/SextantSample.Maui/Views/HomeView.xaml.cs b/Sample/SextantSample.Maui/Views/HomeView.xaml.cs
new file mode 100644
index 00000000..3aebd213
--- /dev/null
+++ b/Sample/SextantSample.Maui/Views/HomeView.xaml.cs
@@ -0,0 +1,27 @@
+using System.Reactive.Disposables;
+
+namespace SextantSample.Maui.Views
+{
+ public partial class HomeView : ReactiveContentPage
+ {
+ public HomeView()
+ {
+ InitializeComponent();
+
+ this.WhenActivated(disposables =>
+ {
+ this.BindCommand(ViewModel, x => x.OpenModal, x => x.FirstModalButton).DisposeWith(disposables);
+ this.BindCommand(ViewModel, x => x.PushPage, x => x.PushPage).DisposeWith(disposables);
+ this.BindCommand(ViewModel, x => x.PushGenericPage, x => x.PushGenericPage).DisposeWith(disposables);
+ });
+
+ Interactions
+ .ErrorMessage
+ .RegisterHandler(async x =>
+ {
+ await DisplayAlert("Error", x.Input.Message, "Done");
+ x.SetOutput(true);
+ });
+ }
+ }
+}
diff --git a/Sample/SextantSample.Maui/Views/RedView.xaml b/Sample/SextantSample.Maui/Views/RedView.xaml
new file mode 100644
index 00000000..f71c9810
--- /dev/null
+++ b/Sample/SextantSample.Maui/Views/RedView.xaml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Sample/SextantSample.Maui/Views/RedView.xaml.cs b/Sample/SextantSample.Maui/Views/RedView.xaml.cs
new file mode 100644
index 00000000..94d76f65
--- /dev/null
+++ b/Sample/SextantSample.Maui/Views/RedView.xaml.cs
@@ -0,0 +1,22 @@
+namespace SextantSample.Maui.Views
+{
+ public partial class RedView : ReactiveContentPage
+ {
+ public RedView()
+ {
+ InitializeComponent();
+ this.BindCommand(ViewModel, x => x.PopModal, x => x.PopModal);
+ this.BindCommand(ViewModel, x => x.PushPage, x => x.PushPage);
+ this.BindCommand(ViewModel, x => x.PopPage, x => x.PopPage);
+ this.BindCommand(ViewModel, x => x.PopToRoot, x => x.PopToRoot);
+
+ Interactions
+ .ErrorMessage
+ .RegisterHandler(async x =>
+ {
+ await DisplayAlert("Error", x.Input.Message, "Done");
+ x.SetOutput(true);
+ });
+ }
+ }
+}
diff --git a/Sample/SextantSample.Maui/Views/SecondModalView.xaml b/Sample/SextantSample.Maui/Views/SecondModalView.xaml
new file mode 100644
index 00000000..3c618242
--- /dev/null
+++ b/Sample/SextantSample.Maui/Views/SecondModalView.xaml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/Sample/SextantSample.Maui/Views/SecondModalView.xaml.cs b/Sample/SextantSample.Maui/Views/SecondModalView.xaml.cs
new file mode 100644
index 00000000..c1a9a5e6
--- /dev/null
+++ b/Sample/SextantSample.Maui/Views/SecondModalView.xaml.cs
@@ -0,0 +1,20 @@
+namespace SextantSample.Maui.Views
+{
+ public partial class SecondModalView : ReactiveContentPage
+ {
+ public SecondModalView()
+ {
+ InitializeComponent();
+ this.BindCommand(ViewModel, x => x.PushPage, x => x.PushPage);
+ this.BindCommand(ViewModel, x => x.PopModal, x => x.PopModal);
+
+ Interactions
+ .ErrorMessage
+ .RegisterHandler(async x =>
+ {
+ await DisplayAlert("Error", x.Input.Message, "Done");
+ x.SetOutput(true);
+ });
+ }
+ }
+}
diff --git a/Sample/SextantSample.iOS/SextantSample.iOS.csproj b/Sample/SextantSample.iOS/SextantSample.iOS.csproj
index 53ad685d..4c290249 100644
--- a/Sample/SextantSample.iOS/SextantSample.iOS.csproj
+++ b/Sample/SextantSample.iOS/SextantSample.iOS.csproj
@@ -103,6 +103,46 @@
+
+ true
+ bin\x64\Debug\
+ __IOS__;__MOBILE__;__UNIFIED__;DEBUG;LOGGING
+ full
+ x64
+ false
+ 7.3
+ prompt
+
+
+ bin\x64\Release\
+ __IOS__;__MOBILE__;__UNIFIED__;
+ true
+ x64
+ false
+ 7.3
+ prompt
+
+
+ bin\x64\Ad-Hoc\
+ __IOS__;__MOBILE__;__UNIFIED__;
+ x64
+ false
+ 7.3
+
+
+ bin\x64\AppStore\
+ __IOS__;__MOBILE__;__UNIFIED__;
+ x64
+ false
+ 7.3
+
+
+ bin\x64\Sample Release\
+ __IOS__;__MOBILE__;__UNIFIED__;
+ x64
+ false
+ 7.3
+
@@ -162,7 +202,7 @@
-
+
@@ -176,4 +216,4 @@
Sextant
-
+
\ No newline at end of file
diff --git a/Sample/SextantSample.sln b/Sample/SextantSample.sln
index c75e527a..1ef665bb 100644
--- a/Sample/SextantSample.sln
+++ b/Sample/SextantSample.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.28803.202
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31717.71
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SextantSample", "SextantSample\SextantSample.csproj", "{AB35E5EE-24AE-479A-909E-1FD941E152EF}"
EndProject
@@ -15,23 +15,34 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sextant.XamForms", "..\src\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SextantSample.ViewModels", "SextantSample.Core\SextantSample.ViewModels.csproj", "{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SextantSample.Maui", "SextantSample.Maui\SextantSample.Maui.csproj", "{7CABE10D-4CDE-4012-9385-6E49EE2E492F}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libs", "Libs", "{637F2480-8306-4A3C-8E97-CB12D5FC3676}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sextant.Maui", "..\src\Sextant.Maui\Sextant.Maui.csproj", "{21A3E901-0F54-4970-B994-09F0574D42E0}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
Ad-Hoc|iPhone = Ad-Hoc|iPhone
Ad-Hoc|iPhoneSimulator = Ad-Hoc|iPhoneSimulator
+ Ad-Hoc|x64 = Ad-Hoc|x64
AppStore|Any CPU = AppStore|Any CPU
AppStore|iPhone = AppStore|iPhone
AppStore|iPhoneSimulator = AppStore|iPhoneSimulator
+ AppStore|x64 = AppStore|x64
Debug|Any CPU = Debug|Any CPU
Debug|iPhone = Debug|iPhone
Debug|iPhoneSimulator = Debug|iPhoneSimulator
+ Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
Release|iPhone = Release|iPhone
Release|iPhoneSimulator = Release|iPhoneSimulator
+ Release|x64 = Release|x64
Sample Release|Any CPU = Sample Release|Any CPU
Sample Release|iPhone = Sample Release|iPhone
Sample Release|iPhoneSimulator = Sample Release|iPhoneSimulator
+ Sample Release|x64 = Sample Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
@@ -40,30 +51,39 @@ Global
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+ {AB35E5EE-24AE-479A-909E-1FD941E152EF}.Ad-Hoc|x64.ActiveCfg = Debug|x64
+ {AB35E5EE-24AE-479A-909E-1FD941E152EF}.Ad-Hoc|x64.Build.0 = Debug|x64
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.AppStore|Any CPU.Build.0 = Release|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.AppStore|iPhone.Build.0 = Debug|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+ {AB35E5EE-24AE-479A-909E-1FD941E152EF}.AppStore|x64.ActiveCfg = Debug|x64
+ {AB35E5EE-24AE-479A-909E-1FD941E152EF}.AppStore|x64.Build.0 = Debug|x64
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Debug|iPhone.Build.0 = Debug|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {AB35E5EE-24AE-479A-909E-1FD941E152EF}.Debug|x64.ActiveCfg = Debug|x64
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Release|Any CPU.Build.0 = Release|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Release|iPhone.ActiveCfg = Release|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Release|iPhone.Build.0 = Release|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {AB35E5EE-24AE-479A-909E-1FD941E152EF}.Release|x64.ActiveCfg = Release|x64
+ {AB35E5EE-24AE-479A-909E-1FD941E152EF}.Release|x64.Build.0 = Release|x64
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Sample Release|Any CPU.ActiveCfg = Release|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Sample Release|Any CPU.Build.0 = Release|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Sample Release|iPhone.ActiveCfg = Release|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Sample Release|iPhone.Build.0 = Release|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Sample Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{AB35E5EE-24AE-479A-909E-1FD941E152EF}.Sample Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {AB35E5EE-24AE-479A-909E-1FD941E152EF}.Sample Release|x64.ActiveCfg = Release|x64
+ {AB35E5EE-24AE-479A-909E-1FD941E152EF}.Sample Release|x64.Build.0 = Release|x64
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Ad-Hoc|Any CPU.ActiveCfg = Sample Release|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Ad-Hoc|Any CPU.Build.0 = Sample Release|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Ad-Hoc|Any CPU.Deploy.0 = Sample Release|Any CPU
@@ -72,6 +92,9 @@ Global
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Sample Release|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Ad-Hoc|iPhoneSimulator.Build.0 = Sample Release|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Sample Release|Any CPU
+ {4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Ad-Hoc|x64.ActiveCfg = Debug|x64
+ {4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Ad-Hoc|x64.Build.0 = Debug|x64
+ {4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Ad-Hoc|x64.Deploy.0 = Debug|x64
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.AppStore|Any CPU.ActiveCfg = Sample Release|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.AppStore|Any CPU.Build.0 = Sample Release|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.AppStore|Any CPU.Deploy.0 = Sample Release|Any CPU
@@ -80,6 +103,9 @@ Global
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.AppStore|iPhoneSimulator.ActiveCfg = Sample Release|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.AppStore|iPhoneSimulator.Build.0 = Sample Release|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.AppStore|iPhoneSimulator.Deploy.0 = Sample Release|Any CPU
+ {4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.AppStore|x64.ActiveCfg = Debug|x64
+ {4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.AppStore|x64.Build.0 = Debug|x64
+ {4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.AppStore|x64.Deploy.0 = Debug|x64
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
@@ -87,6 +113,7 @@ Global
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Debug|iPhone.Build.0 = Debug|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Debug|x64.ActiveCfg = Debug|x64
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Release|Any CPU.Build.0 = Release|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Release|Any CPU.Deploy.0 = Release|Any CPU
@@ -94,6 +121,9 @@ Global
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Release|iPhone.Build.0 = Release|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Release|x64.ActiveCfg = Release|x64
+ {4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Release|x64.Build.0 = Release|x64
+ {4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Release|x64.Deploy.0 = Release|x64
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Sample Release|Any CPU.ActiveCfg = Sample Release|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Sample Release|Any CPU.Build.0 = Sample Release|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Sample Release|Any CPU.Deploy.0 = Sample Release|Any CPU
@@ -103,130 +133,276 @@ Global
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Sample Release|iPhoneSimulator.ActiveCfg = Sample Release|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Sample Release|iPhoneSimulator.Build.0 = Sample Release|Any CPU
{4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Sample Release|iPhoneSimulator.Deploy.0 = Sample Release|Any CPU
+ {4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Sample Release|x64.ActiveCfg = Sample Release|x64
+ {4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Sample Release|x64.Build.0 = Sample Release|x64
+ {4A684BB2-2CB4-4B04-8541-FF0FA677DD49}.Sample Release|x64.Deploy.0 = Sample Release|x64
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+ {4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Ad-Hoc|x64.ActiveCfg = Debug|x64
+ {4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Ad-Hoc|x64.Build.0 = Debug|x64
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.AppStore|Any CPU.Build.0 = Release|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.AppStore|iPhone.Build.0 = Debug|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+ {4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.AppStore|x64.ActiveCfg = Debug|x64
+ {4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.AppStore|x64.Build.0 = Debug|x64
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Debug|iPhone.Build.0 = Debug|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Debug|x64.Build.0 = Debug|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Release|Any CPU.Build.0 = Release|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Release|iPhone.ActiveCfg = Release|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Release|iPhone.Build.0 = Release|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Release|x64.ActiveCfg = Release|x64
+ {4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Release|x64.Build.0 = Release|x64
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Sample Release|Any CPU.ActiveCfg = Release|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Sample Release|Any CPU.Build.0 = Release|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Sample Release|iPhone.ActiveCfg = Release|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Sample Release|iPhone.Build.0 = Release|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Sample Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Sample Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Sample Release|x64.ActiveCfg = Release|x64
+ {4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3}.Sample Release|x64.Build.0 = Release|x64
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|Any CPU
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Ad-Hoc|Any CPU.Build.0 = Ad-Hoc|Any CPU
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator
+ {A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Ad-Hoc|x64.ActiveCfg = Ad-Hoc|x64
+ {A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Ad-Hoc|x64.Build.0 = Ad-Hoc|x64
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.AppStore|Any CPU.ActiveCfg = AppStore|Any CPU
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.AppStore|Any CPU.Build.0 = AppStore|Any CPU
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.AppStore|iPhone.Build.0 = AppStore|iPhone
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator
+ {A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.AppStore|x64.ActiveCfg = AppStore|x64
+ {A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.AppStore|x64.Build.0 = AppStore|x64
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Debug|iPhone.ActiveCfg = Debug|iPhone
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Debug|iPhone.Build.0 = Debug|iPhone
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
+ {A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Debug|x64.ActiveCfg = Debug|x64
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Release|Any CPU.ActiveCfg = Sample Release|Any CPU
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Release|Any CPU.Build.0 = Sample Release|Any CPU
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Release|iPhone.ActiveCfg = Release|iPhone
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Release|iPhone.Build.0 = Release|iPhone
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
+ {A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Release|x64.ActiveCfg = Release|x64
+ {A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Release|x64.Build.0 = Release|x64
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Sample Release|Any CPU.ActiveCfg = Sample Release|Any CPU
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Sample Release|Any CPU.Build.0 = Sample Release|Any CPU
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Sample Release|iPhone.ActiveCfg = Sample Release|iPhone
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Sample Release|iPhone.Build.0 = Sample Release|iPhone
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Sample Release|iPhoneSimulator.ActiveCfg = Sample Release|iPhoneSimulator
{A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Sample Release|iPhoneSimulator.Build.0 = Sample Release|iPhoneSimulator
+ {A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Sample Release|x64.ActiveCfg = Sample Release|x64
+ {A5BBADB1-F348-49CD-8264-59B5BE8E9F17}.Sample Release|x64.Build.0 = Sample Release|x64
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {4529D741-5B1E-4A05-9FDA-36625C12FC33}.Ad-Hoc|x64.ActiveCfg = Debug|x64
+ {4529D741-5B1E-4A05-9FDA-36625C12FC33}.Ad-Hoc|x64.Build.0 = Debug|x64
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.AppStore|iPhone.ActiveCfg = Release|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.AppStore|iPhone.Build.0 = Release|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {4529D741-5B1E-4A05-9FDA-36625C12FC33}.AppStore|x64.ActiveCfg = Debug|x64
+ {4529D741-5B1E-4A05-9FDA-36625C12FC33}.AppStore|x64.Build.0 = Debug|x64
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Debug|iPhone.Build.0 = Debug|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {4529D741-5B1E-4A05-9FDA-36625C12FC33}.Debug|x64.ActiveCfg = Debug|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Release|Any CPU.Build.0 = Release|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Release|iPhone.ActiveCfg = Release|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Release|iPhone.Build.0 = Release|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {4529D741-5B1E-4A05-9FDA-36625C12FC33}.Release|x64.ActiveCfg = Release|x64
+ {4529D741-5B1E-4A05-9FDA-36625C12FC33}.Release|x64.Build.0 = Release|x64
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Sample Release|Any CPU.ActiveCfg = Release|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Sample Release|Any CPU.Build.0 = Release|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Sample Release|iPhone.ActiveCfg = Release|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Sample Release|iPhone.Build.0 = Release|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Sample Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{4529D741-5B1E-4A05-9FDA-36625C12FC33}.Sample Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {4529D741-5B1E-4A05-9FDA-36625C12FC33}.Sample Release|x64.ActiveCfg = Release|x64
+ {4529D741-5B1E-4A05-9FDA-36625C12FC33}.Sample Release|x64.Build.0 = Release|x64
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+ {5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Ad-Hoc|x64.ActiveCfg = Debug|x64
+ {5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Ad-Hoc|x64.Build.0 = Debug|x64
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.AppStore|Any CPU.Build.0 = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.AppStore|iPhone.ActiveCfg = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.AppStore|iPhone.Build.0 = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+ {5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.AppStore|x64.ActiveCfg = Debug|x64
+ {5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.AppStore|x64.Build.0 = Debug|x64
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Debug|iPhone.Build.0 = Debug|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Debug|x64.ActiveCfg = Debug|x64
+ {5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Debug|x64.Build.0 = Debug|x64
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Release|Any CPU.Build.0 = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Release|iPhone.ActiveCfg = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Release|iPhone.Build.0 = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Release|x64.ActiveCfg = Release|x64
+ {5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Release|x64.Build.0 = Release|x64
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Sample Release|Any CPU.ActiveCfg = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Sample Release|Any CPU.Build.0 = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Sample Release|iPhone.ActiveCfg = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Sample Release|iPhone.Build.0 = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Sample Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Sample Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Sample Release|x64.ActiveCfg = Release|x64
+ {5818A5AF-3FF6-4E68-80FC-604D4AEF156C}.Sample Release|x64.Build.0 = Release|x64
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Ad-Hoc|Any CPU.Deploy.0 = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Ad-Hoc|iPhone.Deploy.0 = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Ad-Hoc|x64.ActiveCfg = Debug|x64
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Ad-Hoc|x64.Build.0 = Debug|x64
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Ad-Hoc|x64.Deploy.0 = Debug|x64
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.AppStore|Any CPU.Deploy.0 = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.AppStore|iPhone.Deploy.0 = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.AppStore|iPhoneSimulator.Deploy.0 = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.AppStore|x64.ActiveCfg = Debug|x64
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.AppStore|x64.Build.0 = Debug|x64
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.AppStore|x64.Deploy.0 = Debug|x64
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Debug|iPhone.Deploy.0 = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Debug|x64.ActiveCfg = Debug|x64
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Debug|x64.Build.0 = Debug|x64
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Debug|x64.Deploy.0 = Debug|x64
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Release|iPhone.Build.0 = Release|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Release|iPhone.Deploy.0 = Release|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Release|x64.ActiveCfg = Release|x64
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Release|x64.Build.0 = Release|x64
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Release|x64.Deploy.0 = Release|x64
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Sample Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Sample Release|Any CPU.Build.0 = Release|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Sample Release|Any CPU.Deploy.0 = Release|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Sample Release|iPhone.ActiveCfg = Release|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Sample Release|iPhone.Build.0 = Release|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Sample Release|iPhone.Deploy.0 = Release|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Sample Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Sample Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Sample Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Sample Release|x64.ActiveCfg = Release|x64
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Sample Release|x64.Build.0 = Release|x64
+ {7CABE10D-4CDE-4012-9385-6E49EE2E492F}.Sample Release|x64.Deploy.0 = Release|x64
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Ad-Hoc|x64.ActiveCfg = Debug|x64
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Ad-Hoc|x64.Build.0 = Debug|x64
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.AppStore|x64.ActiveCfg = Debug|x64
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.AppStore|x64.Build.0 = Debug|x64
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Debug|x64.Build.0 = Debug|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Release|iPhone.Build.0 = Release|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Release|x64.ActiveCfg = Release|x64
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Release|x64.Build.0 = Release|x64
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Sample Release|Any CPU.ActiveCfg = Release|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Sample Release|Any CPU.Build.0 = Release|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Sample Release|iPhone.ActiveCfg = Release|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Sample Release|iPhone.Build.0 = Release|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Sample Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Sample Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Sample Release|x64.ActiveCfg = Release|x64
+ {21A3E901-0F54-4970-B994-09F0574D42E0}.Sample Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {4CF5E8D0-BB2C-4790-9AD5-03AEC069C3C3} = {637F2480-8306-4A3C-8E97-CB12D5FC3676}
+ {4529D741-5B1E-4A05-9FDA-36625C12FC33} = {637F2480-8306-4A3C-8E97-CB12D5FC3676}
+ {21A3E901-0F54-4970-B994-09F0574D42E0} = {637F2480-8306-4A3C-8E97-CB12D5FC3676}
+ EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F9AB7F21-AD32-47C9-A787-767DD85B40CB}
EndGlobalSection
diff --git a/Sample/SextantSample/SextantSample.csproj b/Sample/SextantSample/SextantSample.csproj
index 074faa76..1f3b0e31 100644
--- a/Sample/SextantSample/SextantSample.csproj
+++ b/Sample/SextantSample/SextantSample.csproj
@@ -2,9 +2,10 @@
netstandard2.0
+ AnyCPU;x64
-
+
diff --git a/Sample/global.json b/Sample/global.json
new file mode 100644
index 00000000..5cfa01d9
--- /dev/null
+++ b/Sample/global.json
@@ -0,0 +1,5 @@
+{
+ "msbuild-sdks": {
+ "MSBuild.Sdk.Extras": "3.0.44"
+ }
+}
diff --git a/src/Directory.build.props b/src/Directory.build.props
index 2eab6bee..28bf6a2a 100644
--- a/src/Directory.build.props
+++ b/src/Directory.build.props
@@ -5,6 +5,7 @@
MIT
https://github.com/reactiveui/sextant/
https://github.com/reactiveui/styleguide/blob/master/logo_sextant/logo.png?raw=true
+ README.md
.NET Foundation and Contributors
mvvm;reactiveui;Rx;Reactive Extensions;Observable;xamarin;xamarin ios;xamarin mac;android;monodroid;uwp;net461
A ReactiveUI navigation library for Xamarin.Forms
@@ -21,19 +22,36 @@
$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
CS8600;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8623;CS8624;CS8625;CS8626;CS8627;CS8628;CS8629;CS8630;CS8634;CS8766;CS8767
+ preview
+ True
+ latest
+ nullable
+ true
+ true
+ true
+
+
+
+ true
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
all
runtime; build; native; contentfiles; analyzers
@@ -41,16 +59,15 @@
+
-
-
-
+
+
-
-
+
diff --git a/src/Directory.build.targets b/src/Directory.build.targets
index 7469e6b5..8c56efb8 100644
--- a/src/Directory.build.targets
+++ b/src/Directory.build.targets
@@ -4,26 +4,72 @@
$(AssemblyName) ($(TargetFramework))
-
- $(DefineConstants);NET_45;XAML
+
+ $(DefineConstants);NETSTANDARD;PORTABLE
-
- $(DefineConstants);NETFX_CORE;XAML;WINDOWS_UWP
+
+ $(DefineConstants);NET_461;XAML
- $(DefineConstants);MONO;UIKIT;COCOA
+ $(DefineConstants);MONO;UIKIT;COCOA;IOS
+
+
+ $(DefineConstants);MONO;UIKIT;COCOA;IOS
+
+
+ $(DefineConstants);MONO;UIKIT;COCOA;IOS
+
+
+ $(DefineConstants);MONO;UIKIT;COCOA;IOS
+
+
+ $(DefineConstants);MONO;UIKIT;COCOA;IOS
+
+
+ $(DefineConstants);MONO;UIKIT;COCOA;IOS
+
+
+ $(DefineConstants);MONO;UIKIT;COCOA;IOS
- $(DefineConstants);MONO;COCOA
+ $(DefineConstants);MONO;COCOA;MAC
+
+
+ $(DefineConstants);MONO;COCOA;MAC
+
+
+ $(DefineConstants);MONO;COCOA;MAC
+
+
+ $(DefineConstants);MONO;COCOA;MAC
- $(DefineConstants);MONO;UIKIT;COCOA
+ $(DefineConstants);MONO;UIKIT;COCOA;TVOS
+
+
+ $(DefineConstants);MONO;UIKIT;COCOA;TVOS
+
+
+ $(DefineConstants);MONO;UIKIT;COCOA;TVOS
+
+
+ $(DefineConstants);MONO;UIKIT;COCOA;TVOS
- $(DefineConstants);MONO;UIKIT;COCOA
+ $(DefineConstants);MONO;UIKIT;COCOA;WATCHOS
$(DefineConstants);MONO;ANDROID
+ false
+
+
+ $(DefineConstants);MONO;ANDROID
+
+
+ $(DefineConstants);MONO;ANDROID
+
+
+ $(DefineConstants);MONO;ANDROID
$(DefineConstants);TIZEN
diff --git a/src/Sextant.Avalonia/Sextant.Avalonia.csproj b/src/Sextant.Avalonia/Sextant.Avalonia.csproj
index 129cac8e..473aa83e 100644
--- a/src/Sextant.Avalonia/Sextant.Avalonia.csproj
+++ b/src/Sextant.Avalonia/Sextant.Avalonia.csproj
@@ -8,7 +8,7 @@
latest
-
+
diff --git a/src/Sextant.Maui/Behaviors/BehaviorBase.cs b/src/Sextant.Maui/Behaviors/BehaviorBase.cs
new file mode 100644
index 00000000..626b07a1
--- /dev/null
+++ b/src/Sextant.Maui/Behaviors/BehaviorBase.cs
@@ -0,0 +1,66 @@
+// 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.Reactive.Disposables;
+using System.Reactive.Linq;
+
+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..28332c7d
--- /dev/null
+++ b/src/Sextant.Maui/Behaviors/NavigationPageSystemPopBehavior.cs
@@ -0,0 +1,70 @@
+// 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.Reactive.Disposables;
+using System.Reactive.Linq;
+
+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/GlobalUsings.cs b/src/Sextant.Maui/GlobalUsings.cs
new file mode 100644
index 00000000..78e76af2
--- /dev/null
+++ b/src/Sextant.Maui/GlobalUsings.cs
@@ -0,0 +1,9 @@
+// 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.
+
+global using Microsoft.Maui;
+global using Microsoft.Maui.Controls;
+global using ReactiveUI;
+global using Splat;
diff --git a/src/Sextant.Maui/Mixins/DependencyResolverMixins.cs b/src/Sextant.Maui/Mixins/DependencyResolverMixins.cs
new file mode 100644
index 00000000..1d961e11
--- /dev/null
+++ b/src/Sextant.Maui/Mixins/DependencyResolverMixins.cs
@@ -0,0 +1,105 @@
+// 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.Diagnostics.CodeAnalysis;
+using System.Reactive.Concurrency;
+
+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..532a8ef8
--- /dev/null
+++ b/src/Sextant.Maui/Mixins/SextantExtensions.cs
@@ -0,0 +1,32 @@
+// 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
+{
+ ///
+ /// Extension methods interact with .
+ ///
+ public static class SextantExtensions
+ {
+ ///
+ /// Initializes the sextant.
+ ///
+ /// The sextant.
+ public static void InitializeMaui(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..469bdd45
--- /dev/null
+++ b/src/Sextant.Maui/NavigationView.cs
@@ -0,0 +1,225 @@
+// 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;
+
+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..cc384eda
--- /dev/null
+++ b/src/Sextant.Maui/Sextant.Maui.csproj
@@ -0,0 +1,32 @@
+
+
+
+ net7.0;net8.0
+ enable
+ Sextant.Maui
+ Sextant.Maui
+ Sextant.Maui
+ enable
+ latest
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Sextant.Mocks/Sextant.Mocks.csproj b/src/Sextant.Mocks/Sextant.Mocks.csproj
index a3aa1915..cbcf952c 100644
--- a/src/Sextant.Mocks/Sextant.Mocks.csproj
+++ b/src/Sextant.Mocks/Sextant.Mocks.csproj
@@ -1,8 +1,8 @@
- netstandard2.0;net5.0
- $(TargetFrameworks);net461;uap10.0.16299
+ netstandard2.0;net6.0;net7.0;net8.0
+ $(TargetFrameworks);net461;
false
enable
latest
diff --git a/src/Sextant.Plugins.Popup.Tests/API/ApiApprovalTests.SextantPluginsPopup.netcoreapp3.1.approved.txt b/src/Sextant.Plugins.Popup.Tests/API/ApiApprovalTests.SextantPluginsPopup.netcoreapp3.1.approved.txt
deleted file mode 100644
index 528de40d..00000000
--- a/src/Sextant.Plugins.Popup.Tests/API/ApiApprovalTests.SextantPluginsPopup.netcoreapp3.1.approved.txt
+++ /dev/null
@@ -1,67 +0,0 @@
-[assembly: System.Reflection.AssemblyMetadata("RepositoryUrl", "https://github.com/reactiveui/sextant")]
-[assembly: System.Runtime.Versioning.TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName="")]
-namespace Sextant.Plugins.Popup
-{
- public interface IPopupViewStackService : Sextant.IParameterViewStackService, Sextant.IViewStackService
- {
- System.IObservable Popped { get; }
- System.IObservable Popping { get; }
- System.Collections.Generic.IReadOnlyList PopupStack { get; }
- System.IObservable Pushed { get; }
- System.IObservable Pushing { get; }
- System.IObservable PopAllPopups(bool animate = true);
- System.IObservable PopPopup(bool animate = true);
- System.IObservable PushPopup(Sextant.IViewModel viewModel, string? contract = null, bool animate = true);
- System.IObservable PushPopup(Sextant.INavigable viewModel, Sextant.INavigationParameter navigationParameter, string? contract = null, bool animate = true);
- System.IObservable PushPopup(string? contract = null, bool animate = true)
- where TViewModel : Sextant.IViewModel;
- System.IObservable PushPopup(Sextant.INavigationParameter navigationParameter, string? contract = null, bool animate = true)
- where TViewModel : Sextant.INavigable;
- System.IObservable RemovePopup(Sextant.IViewModel viewModel, string? contract = null, bool animate = true);
- }
- public class PopupNavigationEvent
- {
- public PopupNavigationEvent(ReactiveUI.IViewFor page, bool isAnimated) { }
- public bool IsAnimated { get; }
- public Sextant.IViewModel ViewModel { get; }
- }
- public sealed class PopupViewStackService : Sextant.Plugins.Popup.PopupViewStackServiceBase
- {
- public PopupViewStackService(Sextant.IView view, Rg.Plugins.Popup.Contracts.IPopupNavigation popupNavigation, ReactiveUI.IViewLocator viewLocator, Sextant.IViewModelFactory viewModelFactory) { }
- }
- public abstract class PopupViewStackServiceBase : Sextant.ParameterViewStackServiceBase, Sextant.IParameterViewStackService, Sextant.IViewStackService, Sextant.Plugins.Popup.IPopupViewStackService
- {
- protected PopupViewStackServiceBase(Sextant.IView view, Rg.Plugins.Popup.Contracts.IPopupNavigation popupNavigation, ReactiveUI.IViewLocator viewLocator, Sextant.IViewModelFactory viewModelFactory) { }
- public System.IObservable Popped { get; }
- public System.IObservable Popping { get; }
- public System.Collections.Generic.IReadOnlyList PopupStack { get; }
- protected System.Reactive.Subjects.BehaviorSubject> PopupSubject { get; }
- public System.IObservable Pushed { get; }
- public System.IObservable Pushing { get; }
- public System.IObservable PopAllPopups(bool animate = true) { }
- public System.IObservable PopPopup(bool animate = true) { }
- public System.IObservable PushPopup(Sextant.IViewModel viewModel, string? contract = null, bool animate = true) { }
- public System.IObservable PushPopup(Sextant.INavigable viewModel, Sextant.INavigationParameter navigationParameter, string? contract = null, bool animate = true) { }
- public System.IObservable PushPopup(string? contract = null, bool animate = true)
- where TViewModel : Sextant.IViewModel { }
- public System.IObservable PushPopup(Sextant.INavigationParameter navigationParameter, string? contract = null, bool animate = true)
- where TViewModel : Sextant.INavigable { }
- public System.IObservable RemovePopup(Sextant.IViewModel viewModel, string? contract = null, bool animate = true) { }
- }
- public abstract class SextantPopupPage : Rg.Plugins.Popup.Pages.PopupPage, ReactiveUI.IActivatableView, ReactiveUI.IViewFor
- {
- public static readonly Xamarin.Forms.BindableProperty ViewModelProperty;
- protected SextantPopupPage() { }
- public System.IObservable BackgroundClick { get; }
- public object? ViewModel { get; set; }
- protected override void OnBindingContextChanged() { }
- }
- public abstract class SextantPopupPage : Sextant.Plugins.Popup.SextantPopupPage, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor
- where TViewModel : class, Sextant.IViewModel
- {
- public static readonly Xamarin.Forms.BindableProperty ViewModelProperty;
- protected SextantPopupPage() { }
- public new TViewModel ViewModel { get; set; }
- protected override void OnBindingContextChanged() { }
- }
-}
\ No newline at end of file
diff --git a/src/Sextant.Plugins.Popup.Tests/API/ApiApprovalTests.cs b/src/Sextant.Plugins.Popup.Tests/API/ApiApprovalTests.cs
deleted file mode 100644
index 9eaeb6a4..00000000
--- a/src/Sextant.Plugins.Popup.Tests/API/ApiApprovalTests.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-// 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.IO;
-using System.Linq;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Text.RegularExpressions;
-using DiffEngine;
-using PublicApiGenerator;
-using Splat;
-using Xunit;
-
-namespace Sextant.Plugins.Popup.Tests
-{
- ///
- /// Tests to make sure that the API matches the approved ones.
- ///
- [ExcludeFromCodeCoverage]
- public class ApiApprovalTests
- {
- private static readonly Regex _removeCoverletSectionRegex = new(@"^namespace Coverlet\.Core\.Instrumentation\.Tracker.*?^}", RegexOptions.Singleline | RegexOptions.Multiline | RegexOptions.Compiled);
-
- ///
- /// Tests to make sure the splat project is approved.
- ///
- [Fact]
- public void SextantPluginsPopup() => CheckApproval(typeof(IPopupViewStackService).Assembly);
-
- private static void CheckApproval(Assembly assembly, [CallerMemberName]string? memberName = null, [CallerFilePath]string? filePath = null)
- {
- var targetFrameworkName = Assembly.GetExecutingAssembly().GetTargetFrameworkName();
-
- var sourceDirectory = Path.GetDirectoryName(filePath);
-
- if (sourceDirectory is null)
- {
- throw new ArgumentException("The directory name is empty for path: " + filePath);
- }
-
- var approvedFileName = Path.Combine(sourceDirectory, $"ApiApprovalTests.{memberName}.{targetFrameworkName}.approved.txt");
- var receivedFileName = Path.Combine(sourceDirectory, $"ApiApprovalTests.{memberName}.{targetFrameworkName}.received.txt");
-
- if (!File.Exists(receivedFileName))
- {
- File.Create(receivedFileName);
- }
-
- if (!File.Exists(approvedFileName))
- {
- File.Create(approvedFileName);
- }
-
- var approvedPublicApi = File.ReadAllText(approvedFileName);
-
- var receivedPublicApi = Filter(assembly.GeneratePublicApi(null));
-
- if (!string.Equals(receivedPublicApi, approvedPublicApi, StringComparison.InvariantCulture))
- {
- File.WriteAllText(receivedFileName, receivedPublicApi);
- DiffRunner.Launch(receivedFileName, approvedFileName);
- }
-
- Assert.Equal(approvedPublicApi, receivedPublicApi);
- }
-
- private static string Filter(string text)
- {
- text = _removeCoverletSectionRegex.Replace(text, string.Empty);
- return string.Join(Environment.NewLine, text.Split(
- new[]
- {
- Environment.NewLine
- },
- StringSplitOptions.RemoveEmptyEntries)
- .Where(l =>
- !l.StartsWith("[assembly: AssemblyVersion(", StringComparison.InvariantCulture) &&
- !l.StartsWith("[assembly: AssemblyFileVersion(", StringComparison.InvariantCulture) &&
- !l.StartsWith("[assembly: AssemblyInformationalVersion(", StringComparison.InvariantCulture) &&
- !string.IsNullOrWhiteSpace(l)));
- }
- }
-}
diff --git a/src/Sextant.Plugins.Popup.Tests/PopupMock.cs b/src/Sextant.Plugins.Popup.Tests/PopupMock.cs
deleted file mode 100644
index f5c6586b..00000000
--- a/src/Sextant.Plugins.Popup.Tests/PopupMock.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-// 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.Plugins.Popup.Tests
-{
- ///
- /// Represents a popup page.
- ///
- public class PopupMock : SextantPopupPage
- {
- }
-}
diff --git a/src/Sextant.Plugins.Popup.Tests/PopupNavigationMock.cs b/src/Sextant.Plugins.Popup.Tests/PopupNavigationMock.cs
deleted file mode 100644
index 52e0551f..00000000
--- a/src/Sextant.Plugins.Popup.Tests/PopupNavigationMock.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-// 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.Linq;
-using System.Threading.Tasks;
-using Rg.Plugins.Popup.Contracts;
-using Rg.Plugins.Popup.Events;
-using Rg.Plugins.Popup.Pages;
-using Xamarin.Forms.Internals;
-
-namespace Sextant.Plugins.Popup.Tests
-{
- ///
- /// A mocked implementation of .
- ///
- public class PopupNavigationMock : IPopupNavigation
- {
- private readonly Stack _stack;
-
- ///
- /// Initializes a new instance of the class.
- ///
- public PopupNavigationMock() => _stack = new Stack();
-
- ///
- public event EventHandler? Pushing;
-
- ///
- public event EventHandler? Pushed;
-
- ///
- public event EventHandler? Popping;
-
- ///
- public event EventHandler? Popped;
-
- ///
- public IReadOnlyList PopupStack => _stack.ToList();
-
- ///
- public Task PushAsync(PopupPage page, bool animate = true)
- {
- Pushing?.Invoke(this, new PopupNavigationEventArgs(page, animate));
- _stack.Push(page);
- Pushed?.Invoke(this, new PopupNavigationEventArgs(page, animate));
- return Task.CompletedTask;
- }
-
- ///
- public Task PopAsync(bool animate = true)
- {
- Popping?.Invoke(this, new PopupNavigationEventArgs(_stack.Peek(), animate));
- var poppedPage = _stack.Pop();
- Popped?.Invoke(this, new PopupNavigationEventArgs(poppedPage, animate));
- return Task.CompletedTask;
- }
-
- ///
- public Task PopAllAsync(bool animate = true)
- {
- var popupTasks = PopupStack.ToList().Select(page => RemovePageAsync(page, animate));
-
- return Task.WhenAll(popupTasks).ContinueWith(_ => _stack.Clear());
- }
-
- ///
- public Task RemovePageAsync(PopupPage page, bool animate = true)
- {
- var remove = _stack.ToList()[EnumerableExtensions.IndexOf(_stack.ToList(), page)];
- _stack.ToList().Remove(remove);
- Popped?.Invoke(this, new PopupNavigationEventArgs(remove, animate));
- return Task.CompletedTask;
- }
- }
-}
diff --git a/src/Sextant.Plugins.Popup.Tests/PopupViewStackServiceFixture.cs b/src/Sextant.Plugins.Popup.Tests/PopupViewStackServiceFixture.cs
deleted file mode 100644
index e21cf185..00000000
--- a/src/Sextant.Plugins.Popup.Tests/PopupViewStackServiceFixture.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-// 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.Reactive;
-using System.Reactive.Linq;
-using NSubstitute;
-using ReactiveUI;
-using ReactiveUI.Testing;
-using Rg.Plugins.Popup.Contracts;
-using Sextant.Mocks;
-
-namespace Sextant.Plugins.Popup.Tests
-{
- internal class PopupViewStackServiceFixture : IBuilder
- {
- private readonly IView _view;
- private IPopupNavigation _popupNavigation;
- private IViewLocator _viewLocator;
- private IViewModelFactory _viewModelFactory;
-
- public PopupViewStackServiceFixture()
- {
- _view = Substitute.For();
- _popupNavigation = Substitute.For();
- _viewLocator = Substitute.For();
- _viewModelFactory = Substitute.For();
-
- _view
- .PushPage(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any())
- .Returns(Observable.Return(Unit.Default));
- _view.PopPage().Returns(Observable.Return(Unit.Default));
- _viewLocator.ResolveView(Arg.Any()).Returns(new PopupMock { ViewModel = new NavigableViewModelMock() });
- _viewModelFactory.Create(Arg.Any()).Returns(new NavigableViewModelMock());
- }
-
- public static implicit operator PopupViewStackService(PopupViewStackServiceFixture fixture) =>
- fixture.Build();
-
- public PopupViewStackServiceFixture WithNavigation(IPopupNavigation popupNavigation) =>
- this.With(out _popupNavigation, popupNavigation);
-
- public PopupViewStackServiceFixture WithViewModelFactory(IViewModelFactory viewModelFactory) =>
- this.With(out _viewModelFactory, viewModelFactory);
-
- public PopupViewStackServiceFixture WithViewLocator(IViewLocator viewLocator) =>
- this.With(out _viewLocator, viewLocator);
-
- private PopupViewStackService Build() =>
- new(_view, _popupNavigation, _viewLocator, _viewModelFactory);
- }
-}
diff --git a/src/Sextant.Plugins.Popup.Tests/PopupViewStackServiceTests.cs b/src/Sextant.Plugins.Popup.Tests/PopupViewStackServiceTests.cs
deleted file mode 100644
index b7a3ca94..00000000
--- a/src/Sextant.Plugins.Popup.Tests/PopupViewStackServiceTests.cs
+++ /dev/null
@@ -1,854 +0,0 @@
-// 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.Linq;
-using System.Threading.Tasks;
-using FluentAssertions;
-using NSubstitute;
-using ReactiveUI;
-using Rg.Plugins.Popup.Contracts;
-using Rg.Plugins.Popup.Events;
-using Rg.Plugins.Popup.Pages;
-using Sextant.Mocks;
-using Xunit;
-
-namespace Sextant.Plugins.Popup.Tests
-{
- ///
- /// Tests the implementation.
- ///
- public sealed class PopupViewStackServiceTests
- {
- ///
- /// Tests that verify the Pushing property.
- ///
- public class ThePushingProperty
- {
- ///
- /// Tests the observer can respond to events.
- ///
- [Fact]
- public void Should_Observe_Pushing()
- {
- // Given
- PopupNavigationEvent? pushing = null;
- var viewModel = new NavigableViewModelMock();
- var popup = new PopupMock
- {
- ViewModel = viewModel
- };
- var navigation = Substitute.For();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(navigation);
- sut.Pushing.Subscribe(x => pushing = x);
-
- // When
- navigation.Pushing += Raise.EventWith(new PopupNavigationEventArgs(popup, true));
-
- if (pushing is null)
- {
- throw new InvalidOperationException("pushing should not be null.");
- }
-
- // Then
- pushing.ViewModel.Should().Be(viewModel);
- }
- }
-
- ///
- /// Tests that verify the Pushed property.
- ///
- public class ThePushedProperty
- {
- ///
- /// Tests the observer can respond to events.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Observe_Pushed()
- {
- // Given
- PopupNavigationEvent? pushing = null;
- var viewModel = new NavigableViewModelMock();
- var popup = new PopupMock
- {
- ViewModel = viewModel
- };
- var navigation = Substitute.For();
- var viewLocator = Substitute.For();
- viewLocator.ResolveView(Arg.Any()).Returns(popup);
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(navigation).WithViewLocator(viewLocator);
- sut.Pushed.Subscribe(x => pushing = x);
-
- // When
- await sut.PushPopup(viewModel);
- navigation.Pushed += Raise.EventWith(new PopupNavigationEventArgs(popup, true));
-
- if (pushing is null)
- {
- throw new InvalidOperationException("pushing should not be null");
- }
-
- // Then
- pushing.ViewModel.Should().Be(viewModel);
- }
- }
-
- ///
- /// Tests that verify the Popping property.
- ///
- public class ThePoppingProperty
- {
- ///
- /// Tests the observer can respond to events.
- ///
- [Fact]
- public void Should_Observe_Pushing()
- {
- // Given
- PopupNavigationEvent? pushing = null;
- var viewModel = new NavigableViewModelMock();
- var popup = new PopupMock
- {
- ViewModel = viewModel
- };
- var navigation = Substitute.For();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(navigation);
- sut.Popping.Subscribe(x => pushing = x);
-
- // When
- navigation.Popping += Raise.EventWith(new PopupNavigationEventArgs(popup, true));
-
- if (pushing is null)
- {
- throw new InvalidOperationException("pushing should not be null");
- }
-
- // Then
- pushing.ViewModel.Should().Be(viewModel);
- }
- }
-
- ///
- /// Tests that verify the Popped property.
- ///
- public class ThePoppedProperty
- {
- ///
- /// Tests the observer can respond to events.
- ///
- [Fact]
- public void Should_Observe_Popped()
- {
- // Given
- PopupNavigationEvent? pushing = null;
- var viewModel = new NavigableViewModelMock();
- var popup = new PopupMock
- {
- ViewModel = viewModel
- };
- var navigation = Substitute.For();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(navigation);
- sut.Popped.Subscribe(x => pushing = x);
-
- // When
- navigation.Popped += Raise.EventWith(new PopupNavigationEventArgs(popup, true));
-
- if (pushing is null)
- {
- throw new InvalidOperationException("pushing should not be null");
- }
-
- // Then
- pushing.ViewModel.Should().Be(viewModel);
- }
-
- ///
- /// Tests the observer can respond to events.
- ///
- [Fact]
- public void Should_Call_Destroy()
- {
- // Given
- PopupNavigationEvent? pushing = null;
- var viewModel = Substitute.For();
- var popup = new PopupMock
- {
- ViewModel = viewModel
- };
- var navigation = Substitute.For();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(navigation);
- sut.Popped.Subscribe(x => pushing = x);
-
- // When
- navigation.Popped += Raise.EventWith(new PopupNavigationEventArgs(popup, true));
-
- // Then
- ((IDestructible)popup.ViewModel).Received(1).Destroy();
- }
- }
-
- ///
- /// Tests that verify the PushPopup method.
- ///
- public class ThePushPopupMethod
- {
- ///
- /// Tests the method calls the decorated method.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_Popup_Navigation()
- {
- // Given
- var viewModel = new NavigableViewModelMock();
- var navigation = Substitute.For();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(navigation);
-
- // When
- await sut.PushPopup(viewModel);
-
- // Then
- await navigation.Received(1).PushAsync(Arg.Any()).ConfigureAwait(false);
- }
-
- ///
- /// Tests the method calls the view locator.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_View_Locator()
- {
- // Given
- var viewModel = new NavigableViewModelMock();
- var viewLocator = Substitute.For();
- viewLocator.ResolveView(Arg.Any()).Returns(new PopupMock());
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithViewLocator(viewLocator);
-
- // When
- await sut.PushPopup(viewModel);
-
- // Then
- viewLocator.Received(1).ResolveView(Arg.Any());
- }
-
- ///
- /// Tests the method emits a Pushing event.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Observe_Pushing()
- {
- // Given
- bool pushing = false;
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(new PopupNavigationMock());
- sut.Pushing.Select(_ => true).Subscribe(x => pushing = x);
-
- // When
- await sut.PushPopup(new NavigableViewModelMock());
-
- // Then
- pushing.Should().BeTrue();
- }
-
- ///
- /// Tests the method emits a Pushed event.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Observe_Pushed()
- {
- // Given
- bool pushed = false;
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(new PopupNavigationMock());
- sut.Pushed.Select(_ => true).Subscribe(x => pushed = x);
-
- // When
- await sut.PushPopup(new NavigableViewModelMock());
-
- // Then
- pushed.Should().BeTrue();
- }
- }
-
- ///
- /// Tests that verify the PushPopup method that takes parameters.
- ///
- public class ThePushPopupWithParametersMethod
- {
- ///
- /// Tests the method calls the decorated method.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_Popup_Navigation()
- {
- // Given
- var parameter = new NavigationParameter();
- var viewModel = new NavigableViewModelMock();
- var navigation = Substitute.For();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(navigation);
-
- // When
- await sut.PushPopup(viewModel, parameter);
-
- // Then
- await navigation.Received(1).PushAsync(Arg.Any()).ConfigureAwait(false);
- }
-
- ///
- /// Tests the method calls the view locator.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_View_Locator()
- {
- // Given
- var parameter = new NavigationParameter();
- var viewModel = new NavigableViewModelMock();
- var viewLocator = Substitute.For();
- viewLocator.ResolveView(Arg.Any()).Returns(new PopupMock());
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithViewLocator(viewLocator);
-
- // When
- await sut.PushPopup(viewModel, parameter);
-
- // Then
- viewLocator.Received(1).ResolveView(Arg.Any());
- }
-
- ///
- /// Tests the method emits a Pushing event.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Observe_Pushing()
- {
- // Given
- bool pushing = false;
- var parameter = new NavigationParameter();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(new PopupNavigationMock());
- sut.Pushing.Select(_ => true).Subscribe(x => pushing = x);
-
- // When
- await sut.PushPopup(new NavigableViewModelMock(), parameter);
-
- // Then
- pushing.Should().BeTrue();
- }
-
- ///
- /// Tests the method emits a Pushed event.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Observe_Pushed()
- {
- // Given
- bool pushed = false;
- var parameter = new NavigationParameter();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(new PopupNavigationMock());
- sut.Pushed.Select(_ => true).Subscribe(x => pushed = x);
-
- // When
- await sut.PushPopup(new NavigableViewModelMock(), parameter);
-
- // Then
- pushed.Should().BeTrue();
- }
-
- ///
- /// Tests the method calls the navigating to method.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_Navigating_To()
- {
- // Given
- var parameter = new NavigationParameter();
- var viewLocator = Substitute.For();
- var viewModel = Substitute.For();
- viewLocator.ResolveView(Arg.Any(), Arg.Any()).Returns(new PopupMock());
- var navigation = Substitute.For();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(navigation);
-
- // When
- await sut.PushPopup(viewModel, parameter);
-
- // Then
- await viewModel.Received(1).WhenNavigatingTo(parameter);
- }
-
- ///
- /// Tests the method calls the navigated to method.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_Navigated_To()
- {
- // Given
- var parameter = new NavigationParameter();
- var viewModel = Substitute.For();
- var viewModelFactory = Substitute.For();
- viewModelFactory.Create().Returns(viewModel);
- var viewLocator = Substitute.For();
- viewLocator.ResolveView(Arg.Any(), Arg.Any()).Returns(new PopupMock());
- var navigation = Substitute.For();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(navigation).WithViewLocator(viewLocator).WithViewModelFactory(viewModelFactory);
-
- // When
- await sut.PushPopup(viewModel, parameter);
-
- // Then
- await viewModel.Received(1).WhenNavigatedTo(parameter);
- }
- }
-
- ///
- /// Tests that verify the PushPopup generic method.
- ///
- public class ThePushPopupGenericMethod
- {
- ///
- /// Tests the method calls the decorated method.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_Popup_Navigation()
- {
- // Given
- var navigation = Substitute.For();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(navigation);
-
- // When
- await sut.PushPopup();
-
- // Then
- await navigation.Received(1).PushAsync(Arg.Any()).ConfigureAwait(false);
- }
-
- ///
- /// Tests the method calls the view model factory.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_View_Model_Factory()
- {
- // Given
- var viewModelFactory = Substitute.For();
- viewModelFactory.Create(Arg.Any()).Returns(new NavigableViewModelMock());
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithViewModelFactory(viewModelFactory);
-
- // When
- await sut.PushPopup();
-
- // Then
- viewModelFactory.Received(1).Create();
- }
-
- ///
- /// Tests the method calls the view locator.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_View_Locator()
- {
- // Given
- var viewLocator = Substitute.For();
- viewLocator.ResolveView(Arg.Any()).Returns(new PopupMock());
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithViewLocator(viewLocator);
-
- // When
- await sut.PushPopup();
-
- // Then
- viewLocator.Received(1).ResolveView(Arg.Any());
- }
-
- ///
- /// Tests the method emits a Pushing event.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Observe_Pushing()
- {
- // Given
- bool pushing = false;
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(new PopupNavigationMock());
- sut.Pushing.Select(_ => true).Subscribe(x => pushing = x);
-
- // When
- await sut.PushPopup();
-
- // Then
- pushing.Should().BeTrue();
- }
-
- ///
- /// Tests the method emits a Pushed event.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Observe_Pushed()
- {
- // Given
- bool pushed = false;
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(new PopupNavigationMock());
- sut.Pushed.Select(_ => true).Subscribe(x => pushed = x);
-
- // When
- await sut.PushPopup();
-
- // Then
- pushed.Should().BeTrue();
- }
- }
-
- ///
- /// Tests that verify the PushPopup generic method that takes parameters.
- ///
- public class ThePushPopupGenericWithParameterMethod
- {
- ///
- /// Tests the method calls the decorated method.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_Popup_Navigation()
- {
- // Given
- var parameter = new NavigationParameter();
- var navigation = Substitute.For();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(navigation);
-
- // When
- await sut.PushPopup(parameter);
-
- // Then
- await navigation.Received(1).PushAsync(Arg.Any()).ConfigureAwait(false);
- }
-
- ///
- /// Tests the method calls the view model factory.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_View_Model_Factory()
- {
- // Given
- var parameter = new NavigationParameter();
- var viewModelFactory = Substitute.For();
- viewModelFactory.Create(Arg.Any()).Returns(new NavigableViewModelMock());
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithViewModelFactory(viewModelFactory);
-
- // When
- await sut.PushPopup(parameter);
-
- // Then
- viewModelFactory.Received(1).Create();
- }
-
- ///
- /// Tests the method calls the view locator.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_View_Locator()
- {
- // Given
- var parameter = new NavigationParameter();
- var viewModel = new NavigableViewModelMock();
- var viewLocator = Substitute.For();
- viewLocator.ResolveView(Arg.Any(), Arg.Any()).Returns(new PopupMock());
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithViewLocator(viewLocator);
-
- // When
- await sut.PushPopup(parameter);
-
- // Then
- viewLocator.Received(1).ResolveView(Arg.Any());
- }
-
- ///
- /// Tests the method emits a Pushing event.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Observe_Pushing()
- {
- // Given
- bool pushing = false;
- var parameter = new NavigationParameter();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(new PopupNavigationMock());
- sut.Pushing.Select(_ => true).Subscribe(x => pushing = x);
-
- // When
- await sut.PushPopup(parameter);
-
- // Then
- pushing.Should().BeTrue();
- }
-
- ///
- /// Tests the method emits a Pushed event.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Observe_Pushed()
- {
- // Given
- bool pushed = false;
- var parameter = new NavigationParameter();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(new PopupNavigationMock());
- sut.Pushed.Select(_ => true).Subscribe(x => pushed = x);
-
- // When
- await sut.PushPopup(parameter);
-
- // Then
- pushed.Should().BeTrue();
- }
-
- ///
- /// Tests the method calls the navigating to method.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_Navigating_To()
- {
- // Given
- var parameter = new NavigationParameter();
- var viewModel = Substitute.For();
- var viewLocator = Substitute.For();
- viewLocator.ResolveView(Arg.Any()).Returns(new PopupMock());
- var factory = Substitute.For();
- factory.Create(Arg.Any()).Returns(viewModel);
- var navigation = Substitute.For();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(navigation).WithViewModelFactory(factory).WithViewLocator(viewLocator);
-
- // When
- await sut.PushPopup(parameter);
-
- // Then
- await viewModel.Received(1).WhenNavigatingTo(parameter);
- }
-
- ///
- /// Tests the method calls the navigated to method.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_Navigated_To()
- {
- // Given
- var parameter = new NavigationParameter();
- var viewModel = Substitute.For();
- var viewLocator = Substitute.For();
- var viewModelFactory = Substitute.For();
- viewModelFactory.Create().Returns(viewModel);
- viewLocator
- .ResolveView(Arg.Any(), Arg.Any())
- .Returns(new PopupMock());
-
- var navigation = Substitute.For();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(navigation).WithViewModelFactory(viewModelFactory).WithViewLocator(viewLocator);
-
- // When
- await sut.PushPopup(parameter);
-
- // Then
- await viewModel.Received(1).WhenNavigatedTo(parameter);
- }
- }
-
- ///
- /// Tests that verify the PopPopup method.
- ///
- public class ThePopPopupMethod
- {
- ///
- /// Tests the method calls the decorated method.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_Popup_Navigation()
- {
- // Given
- var navigation = Substitute.For();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(navigation);
-
- // When
- await sut.PopPopup();
-
- // Then
- await navigation.Received(1).PopAsync(Arg.Any()).ConfigureAwait(false);
- }
-
- ///
- /// Tests the method emits a Popping event.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Observe_Popping()
- {
- // Given
- bool pushing = false;
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(new PopupNavigationMock());
- sut.Popping.Select(_ => true).Subscribe(x => pushing = x);
-
- // When
- await sut.PushPopup(new NavigableViewModelMock());
- await sut.PopPopup();
-
- // Then
- pushing.Should().BeTrue();
- }
-
- ///
- /// Tests the method emits a Popped event.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Observe_Popped()
- {
- // Given
- bool pushed = false;
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(new PopupNavigationMock());
- sut.Popped.Select(_ => true).Subscribe(x => pushed = x);
-
- // When
- await sut.PushPopup(new NavigableViewModelMock());
- await sut.PopPopup();
-
- // Then
- pushed.Should().BeTrue();
- }
-
- ///
- /// Tests the popped view model is destroyed.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_Destroy()
- {
- // Given
- var viewModel = Substitute.For();
- var popup = new PopupMock
- {
- ViewModel = viewModel
- };
- bool pushed = false;
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(new PopupNavigationMock());
- sut.Popped.Select(_ => true).Subscribe(x => pushed = x);
-
- // When
- await sut.PushPopup(viewModel);
- await sut.PopPopup();
-
- // Then
- ((IDestructible)popup.ViewModel).Received(1).Destroy();
- }
- }
-
- ///
- /// Tests that verify the PopAllPopups method.
- ///
- public class ThePopAllPopupsMethod
- {
- ///
- /// Tests the method calls the decorated method.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_Popup_Navigation()
- {
- // Given
- var navigation = Substitute.For();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(navigation);
- await sut.PushPopup(new NavigableViewModelMock());
-
- // When
- await sut.PopAllPopups();
-
- // Then
- await navigation.Received(1).PopAllAsync().ConfigureAwait(false);
- }
-
- ///
- /// Tests the popped view model is destroyed.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_Destroy()
- {
- // Given
- var viewModel = Substitute.For();
- var popup = new PopupMock
- {
- ViewModel = viewModel
- };
- bool pushed = false;
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(new PopupNavigationMock());
- sut.Popped.Select(_ => true).Subscribe(x => pushed = x);
-
- // When
- await sut.PushPopup(viewModel);
- await sut.PopAllPopups();
-
- // Then
- ((IDestructible)popup.ViewModel).Received(1).Destroy();
- }
- }
-
- ///
- /// Tests that verify the RemovePopup method.
- ///
- public class TheRemovePopupMethod
- {
- ///
- /// Tests the method calls the decorated method.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_Popup_Navigation()
- {
- // Given
- var navigation = Substitute.For();
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(navigation);
-
- // When
- await sut.RemovePopup(new NavigableViewModelMock());
-
- // Then
- await navigation.Received(1).RemovePageAsync(Arg.Any()).ConfigureAwait(false);
- }
-
- ///
- /// Tests the popped view model is destroyed.
- ///
- /// A completion notification.
- [Fact]
- public async Task Should_Call_Destroy()
- {
- // Given
- var viewModel = Substitute.For();
- var popup = new PopupMock
- {
- ViewModel = viewModel
- };
- bool pushed = false;
- PopupViewStackService sut = new PopupViewStackServiceFixture().WithNavigation(new PopupNavigationMock());
- sut.Popped.Select(_ => true).Subscribe(x => pushed = x);
-
- // When
- await sut.PushPopup(viewModel);
- await sut.RemovePopup(viewModel);
-
- // Then
- ((IDestructible)popup.ViewModel).Received(1).Destroy();
- }
- }
- }
-}
diff --git a/src/Sextant.Plugins.Popup.Tests/Sextant.Plugins.Popup.Tests.csproj b/src/Sextant.Plugins.Popup.Tests/Sextant.Plugins.Popup.Tests.csproj
deleted file mode 100644
index a0c51f03..00000000
--- a/src/Sextant.Plugins.Popup.Tests/Sextant.Plugins.Popup.Tests.csproj
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
- netcoreapp3.1
- false
- enable
- latest
-
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers
-
-
-
-
-
diff --git a/src/Sextant.Tests/API/ApiApprovalTests.Sextant.net5.0.approved.txt b/src/Sextant.Tests/API/ApiApprovalTests.Sextant.DotNet6_0.verified.txt
similarity index 97%
rename from src/Sextant.Tests/API/ApiApprovalTests.Sextant.net5.0.approved.txt
rename to src/Sextant.Tests/API/ApiApprovalTests.Sextant.DotNet6_0.verified.txt
index 922deb8f..f08047bb 100644
--- a/src/Sextant.Tests/API/ApiApprovalTests.Sextant.net5.0.approved.txt
+++ b/src/Sextant.Tests/API/ApiApprovalTests.Sextant.DotNet6_0.verified.txt
@@ -1,5 +1,4 @@
-[assembly: System.Reflection.AssemblyMetadata("RepositoryUrl", "https://github.com/reactiveui/sextant")]
-[assembly: System.Runtime.Versioning.TargetFramework(".NETCoreApp,Version=v5.0", FrameworkDisplayName="")]
+[assembly: System.Runtime.Versioning.TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName=".NET 6.0")]
namespace Sextant
{
public class DefaultViewModelFactory : Sextant.IViewModelFactory
@@ -193,10 +192,4 @@ namespace Sextant
protected static void PopRootAndTick(System.Reactive.Subjects.BehaviorSubject> stackSubject, System.Reactive.Disposables.CompositeDisposable disposable) { }
protected static T PopStackAndTick(System.Reactive.Subjects.BehaviorSubject> stackSubject) { }
}
-}
-namespace System.Reactive.Linq
-{
- public static class SubscribeSafeExtensions { }
- public static class ToSignalExtension { }
- public static class WhereNotNullExtension { }
}
\ No newline at end of file
diff --git a/src/Sextant.Tests/API/ApiApprovalTests.Sextant.netcoreapp3.1.approved.txt b/src/Sextant.Tests/API/ApiApprovalTests.Sextant.DotNet7_0.verified.txt
similarity index 97%
rename from src/Sextant.Tests/API/ApiApprovalTests.Sextant.netcoreapp3.1.approved.txt
rename to src/Sextant.Tests/API/ApiApprovalTests.Sextant.DotNet7_0.verified.txt
index 0a56a3f8..3249a270 100644
--- a/src/Sextant.Tests/API/ApiApprovalTests.Sextant.netcoreapp3.1.approved.txt
+++ b/src/Sextant.Tests/API/ApiApprovalTests.Sextant.DotNet7_0.verified.txt
@@ -1,5 +1,4 @@
-[assembly: System.Reflection.AssemblyMetadata("RepositoryUrl", "https://github.com/reactiveui/sextant")]
-[assembly: System.Runtime.Versioning.TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName="")]
+[assembly: System.Runtime.Versioning.TargetFramework(".NETCoreApp,Version=v7.0", FrameworkDisplayName=".NET 7.0")]
namespace Sextant
{
public class DefaultViewModelFactory : Sextant.IViewModelFactory
@@ -193,10 +192,4 @@ namespace Sextant
protected static void PopRootAndTick(System.Reactive.Subjects.BehaviorSubject> stackSubject, System.Reactive.Disposables.CompositeDisposable disposable) { }
protected static T PopStackAndTick(System.Reactive.Subjects.BehaviorSubject> stackSubject) { }
}
-}
-namespace System.Reactive.Linq
-{
- public static class SubscribeSafeExtensions { }
- public static class ToSignalExtension { }
- public static class WhereNotNullExtension { }
}
\ No newline at end of file
diff --git a/src/Sextant.Tests/API/ApiApprovalTests.Sextant.DotNet8_0.verified.txt b/src/Sextant.Tests/API/ApiApprovalTests.Sextant.DotNet8_0.verified.txt
new file mode 100644
index 00000000..e5c48c46
--- /dev/null
+++ b/src/Sextant.Tests/API/ApiApprovalTests.Sextant.DotNet8_0.verified.txt
@@ -0,0 +1,196 @@
+[assembly: System.Runtime.Versioning.TargetFramework(".NETCoreApp,Version=v8.0", FrameworkDisplayName=".NET 8.0")]
+namespace Sextant
+{
+ public class DefaultViewModelFactory : Sextant.IViewModelFactory
+ {
+ public DefaultViewModelFactory() { }
+ public TViewModel Create(string? contract = null)
+ where TViewModel : Sextant.IViewModel { }
+ }
+ public static class DependencyResolverMixins
+ {
+ public static string NavigationView { get; }
+ public static Splat.IMutableDependencyResolver RegisterParameterViewStackService(this Splat.IMutableDependencyResolver dependencyResolver) { }
+ [System.Obsolete("Use RegisterViewForNavigation")]
+ public static Splat.IMutableDependencyResolver RegisterView(this Splat.IMutableDependencyResolver dependencyResolver, string? contract = null)
+ where TView : ReactiveUI.IViewFor, new ()
+ where TViewModel : class, Sextant.IViewModel { }
+ [System.Obsolete("Use RegisterViewForNavigation")]
+ public static Splat.IMutableDependencyResolver RegisterView(this Splat.IMutableDependencyResolver dependencyResolver, System.Func viewFactory, string? contract = null)
+ where TView : class, ReactiveUI.IViewFor
+ where TViewModel : class, Sextant.IViewModel { }
+ public static Splat.IMutableDependencyResolver RegisterViewForNavigation(this Splat.IMutableDependencyResolver resolver, System.Func viewFactory, System.Func viewModelFactory)
+ where TView : class, ReactiveUI.IViewFor
+ where TViewModel : class, Sextant.IViewModel { }
+ public static Splat.IMutableDependencyResolver RegisterViewForNavigation(this Splat.IMutableDependencyResolver resolver, TView view, TViewModel viewModel)
+ where TView : class, ReactiveUI.IViewFor
+ where TViewModel : class, Sextant.IViewModel { }
+ [System.Obsolete("Use of new makes this method undesirable.")]
+ public static Splat.IMutableDependencyResolver RegisterViewModel(this Splat.IMutableDependencyResolver dependencyResolver, string? contract = null)
+ where TViewModel : Sextant.IViewModel, new () { }
+ public static Splat.IMutableDependencyResolver RegisterViewModel(this Splat.IMutableDependencyResolver dependencyResolver, System.Func viewModelFactory, string? contract = null)
+ where TViewModel : class, Sextant.IViewModel { }
+ public static Splat.IMutableDependencyResolver RegisterViewModel(this Splat.IMutableDependencyResolver dependencyResolver, TViewModel viewModel, string? contract = null)
+ where TViewModel : class, Sextant.IViewModel { }
+ public static Splat.IMutableDependencyResolver RegisterViewModelFactory(this Splat.IMutableDependencyResolver dependencyResolver) { }
+ public static Splat.IMutableDependencyResolver RegisterViewModelFactory(this Splat.IMutableDependencyResolver dependencyResolver, System.Func factory) { }
+ public static Splat.IMutableDependencyResolver RegisterViewStackService(this Splat.IMutableDependencyResolver dependencyResolver) { }
+ [System.Obsolete("Use the Func variant.")]
+ public static Splat.IMutableDependencyResolver RegisterViewStackService(this Splat.IMutableDependencyResolver dependencyResolver, System.Func factory)
+ where T : Sextant.IViewStackService { }
+ public static Splat.IMutableDependencyResolver RegisterViewStackService(this Splat.IMutableDependencyResolver dependencyResolver, System.Func factory)
+ where T : Sextant.IViewStackService { }
+ }
+ public interface IDestructible
+ {
+ void Destroy();
+ }
+ public interface INavigable : Sextant.INavigated, Sextant.INavigating, Sextant.IViewModel { }
+ public interface INavigated
+ {
+ System.IObservable WhenNavigatedFrom(Sextant.INavigationParameter parameter);
+ System.IObservable WhenNavigatedTo(Sextant.INavigationParameter parameter);
+ }
+ public interface INavigating
+ {
+ System.IObservable WhenNavigatingTo(Sextant.INavigationParameter parameter);
+ }
+ public interface INavigationParameter : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable
+ {
+ T GetValue(string key);
+ bool TryGetValue(string key, out T value);
+ }
+ [System.Obsolete("Please use the IViewModel interface.")]
+ public interface IPageViewModel : Sextant.IViewModel { }
+ public interface IParameterViewStackService : Sextant.IViewStackService
+ {
+ System.IObservable PopPage(Sextant.INavigationParameter parameter, bool animate = true);
+ System.IObservable PushModal(Sextant.INavigable navigableModal, Sextant.INavigationParameter parameter, string? contract = null, bool withNavigationPage = true);
+ System.IObservable PushModal(Sextant.INavigationParameter parameter, string? contract = null, bool withNavigationPage = true)
+ where TViewModel : Sextant.INavigable;
+ System.IObservable PushPage(Sextant.INavigable navigableViewModel, Sextant.INavigationParameter parameter, string? contract = null, bool resetStack = false, bool animate = true);
+ System.IObservable PushPage(Sextant.INavigationParameter parameter, string? contract = null, bool resetStack = false, bool animate = true)
+ where TViewModel : Sextant.INavigable;
+ }
+ public interface IView
+ {
+ System.Reactive.Concurrency.IScheduler MainThreadScheduler { get; }
+ System.IObservable PagePopped { get; }
+ System.IObservable PopModal();
+ System.IObservable PopPage(bool animate = true);
+ System.IObservable PopToRootPage(bool animate = true);
+ System.IObservable PushModal(Sextant.IViewModel modalViewModel, string? contract, bool withNavigationPage = true);
+ System.IObservable PushPage(Sextant.IViewModel viewModel, string? contract, bool resetStack, bool animate = true);
+ }
+ public interface IViewModel
+ {
+ string Id { get; }
+ }
+ public interface IViewModelFactory
+ {
+ TViewModel Create(string? contract = null)
+ where TViewModel : Sextant.IViewModel;
+ }
+ public interface IViewStackService
+ {
+ System.IObservable> ModalStack { get; }
+ System.IObservable> PageStack { get; }
+ Sextant.IView View { get; }
+ System.IObservable PopModal(bool animate = true);
+ System.IObservable PopPage(bool animate = true);
+ System.IObservable PopToRootPage(bool animate = true);
+ System.IObservable PushModal(Sextant.IViewModel modal, string? contract = null, bool withNavigationPage = true);
+ System.IObservable PushModal(string? contract = null, bool withNavigationPage = true)
+ where TViewModel : Sextant.IViewModel;
+ System.IObservable PushPage(Sextant.INavigable page, string? contract = null, bool resetStack = false, bool animate = true);
+ System.IObservable PushPage(Sextant.IViewModel page, string? contract = null, bool resetStack = false, bool animate = true);
+ System.IObservable PushPage(string? contract = null, bool resetStack = false, bool animate = true)
+ where TViewModel : Sextant.IViewModel;
+ System.IObservable TopModal();
+ System.IObservable TopPage();
+ }
+ public class NavigationParameter : System.Collections.Generic.Dictionary, Sextant.INavigationParameter, System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable
+ {
+ public NavigationParameter() { }
+ public T GetValue(string key) { }
+ public bool TryGetValue(string key, out T value) { }
+ }
+ public sealed class ParameterViewStackService : Sextant.ParameterViewStackServiceBase
+ {
+ public ParameterViewStackService(Sextant.IView view) { }
+ public ParameterViewStackService(Sextant.IView view, Sextant.IViewModelFactory viewModelFactory) { }
+ }
+ public abstract class ParameterViewStackServiceBase : Sextant.ViewStackServiceBase, Sextant.IParameterViewStackService, Sextant.IViewStackService
+ {
+ protected ParameterViewStackServiceBase(Sextant.IView view, Sextant.IViewModelFactory viewModelFactory) { }
+ public System.IObservable PopPage(Sextant.INavigationParameter parameter, bool animate = true) { }
+ public System.IObservable PushModal(Sextant.INavigable navigableModal, Sextant.INavigationParameter parameter, string? contract = null, bool withNavigationPage = true) { }
+ public System.IObservable PushModal(Sextant.INavigationParameter parameter, string? contract = null, bool withNavigationPage = true)
+ where TViewModel : Sextant.INavigable { }
+ public System.IObservable PushPage(Sextant.INavigable navigableViewModel, Sextant.INavigationParameter parameter, string? contract = null, bool resetStack = false, bool animate = true) { }
+ public System.IObservable PushPage(Sextant.INavigationParameter parameter, string? contract = null, bool resetStack = false, bool animate = true)
+ where TViewModel : Sextant.INavigable { }
+ }
+ public class Sextant
+ {
+ public Sextant() { }
+ public Splat.IMutableDependencyResolver MutableLocator { get; }
+ public static Sextant.Sextant Instance { get; }
+ }
+ public static class SextantExtensions
+ {
+ public static void Initialize(this Sextant.Sextant sextant) { }
+ }
+ public static class ViewModelActionExtensions
+ {
+ public static object InvokeViewModelAction(this object viewModel, System.Action action)
+ where T : class { }
+ }
+ public static class ViewModelFactory
+ {
+ public static Sextant.IViewModelFactory Current { get; }
+ }
+ [System.Serializable]
+ public class ViewModelFactoryNotFoundException : System.Exception
+ {
+ public ViewModelFactoryNotFoundException() { }
+ public ViewModelFactoryNotFoundException(string message) { }
+ [System.Obsolete(DiagnosticId="SYSLIB0051")]
+ protected ViewModelFactoryNotFoundException(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) { }
+ public ViewModelFactoryNotFoundException(string message, System.Exception innerException) { }
+ }
+ public sealed class ViewStackService : Sextant.ViewStackServiceBase
+ {
+ public ViewStackService(Sextant.IView view) { }
+ public ViewStackService(Sextant.IView view, Sextant.IViewModelFactory viewModelFactory) { }
+ }
+ public abstract class ViewStackServiceBase : Sextant.IViewStackService, Splat.IEnableLogger, System.IDisposable
+ {
+ protected ViewStackServiceBase(Sextant.IView view, Sextant.IViewModelFactory viewModelFactory) { }
+ protected Sextant.IViewModelFactory Factory { get; }
+ protected Splat.IFullLogger Logger { get; }
+ public System.IObservable> ModalStack { get; }
+ protected System.Reactive.Subjects.BehaviorSubject> ModalSubject { get; }
+ protected System.Reactive.Disposables.CompositeDisposable NavigationDisposables { get; }
+ public System.IObservable> PageStack { get; }
+ protected System.Reactive.Subjects.BehaviorSubject> PageSubject { get; }
+ public Sextant.IView View { get; }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ public System.IObservable