feature: .net 5 and C# 9, tvos (#294)
This commit is contained in:
Родитель
2800518c5b
Коммит
d843512b74
|
@ -29,9 +29,13 @@ csharp_new_line_between_query_expression_clauses = true
|
|||
csharp_indent_block_contents = true
|
||||
csharp_indent_braces = false
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_case_contents_when_block = true
|
||||
csharp_indent_switch_labels = true
|
||||
csharp_indent_labels = one_less_than_current
|
||||
|
||||
# Modifier preferences
|
||||
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
|
||||
|
||||
# avoid this. unless absolutely necessary
|
||||
dotnet_style_qualification_for_field = false:suggestion
|
||||
dotnet_style_qualification_for_property = false:suggestion
|
||||
|
@ -40,10 +44,13 @@ dotnet_style_qualification_for_event = false:suggestion
|
|||
|
||||
# only use var when it's obvious what the variable type is
|
||||
csharp_style_var_for_built_in_types = false:none
|
||||
csharp_style_var_when_type_is_apparent = false:suggestion
|
||||
csharp_style_var_elsewhere = false:suggestion
|
||||
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||
csharp_style_var_elsewhere = true:suggestion
|
||||
|
||||
# use language keywords instead of BCL types
|
||||
# Types: use keywords instead of BCL types, and permit var only when the type is clear
|
||||
csharp_style_var_for_built_in_types = false:suggestion
|
||||
csharp_style_var_when_type_is_apparent = false:none
|
||||
csharp_style_var_elsewhere = false:suggestion
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
||||
dotnet_style_predefined_type_for_member_access = true:suggestion
|
||||
|
||||
|
@ -51,33 +58,42 @@ dotnet_style_predefined_type_for_member_access = true:suggestion
|
|||
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
|
||||
|
||||
dotnet_naming_symbols.constant_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.constant_fields.required_modifiers = const
|
||||
|
||||
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
|
||||
|
||||
# static fields should have s_ prefix
|
||||
dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion
|
||||
dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields
|
||||
dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style
|
||||
dotnet_naming_symbols.static_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.static_fields.required_modifiers = static
|
||||
|
||||
dotnet_naming_style.static_prefix_style.capitalization = camel_case
|
||||
dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected
|
||||
dotnet_naming_style.static_prefix_style.required_prefix = s_
|
||||
dotnet_naming_style.static_prefix_style.capitalization = camel_case
|
||||
|
||||
# internal and private fields should be _camelCase
|
||||
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
|
||||
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
|
||||
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
|
||||
|
||||
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
|
||||
|
||||
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
|
||||
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
|
||||
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
|
||||
|
||||
# Code style defaults
|
||||
csharp_using_directive_placement = outside_namespace:suggestion
|
||||
dotnet_sort_system_directives_first = true
|
||||
csharp_preserve_single_line_blocks = true
|
||||
csharp_preserve_single_line_statements = false
|
||||
csharp_prefer_braces = true:silent
|
||||
csharp_preserve_single_line_blocks = true:none
|
||||
csharp_preserve_single_line_statements = false:none
|
||||
csharp_prefer_static_local_function = true:suggestion
|
||||
csharp_prefer_simple_using_statement = false:none
|
||||
csharp_style_prefer_switch_expression = true:suggestion
|
||||
|
||||
# Code quality
|
||||
dotnet_style_readonly_field = true:suggestion
|
||||
dotnet_code_quality_unused_parameters = non_public:suggestion
|
||||
|
||||
# Expression-level preferences
|
||||
dotnet_style_object_initializer = true:suggestion
|
||||
|
@ -85,14 +101,23 @@ dotnet_style_collection_initializer = true:suggestion
|
|||
dotnet_style_explicit_tuple_names = true:suggestion
|
||||
dotnet_style_coalesce_expression = true:suggestion
|
||||
dotnet_style_null_propagation = true:suggestion
|
||||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
|
||||
dotnet_style_prefer_inferred_tuple_names = true:suggestion
|
||||
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
|
||||
dotnet_style_prefer_auto_properties = true:suggestion
|
||||
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
|
||||
dotnet_style_prefer_conditional_expression_over_return = true:silent
|
||||
csharp_prefer_simple_default_expression = true:suggestion
|
||||
|
||||
# Expression-bodied members
|
||||
csharp_style_expression_bodied_methods = false:none
|
||||
csharp_style_expression_bodied_constructors = false:none
|
||||
csharp_style_expression_bodied_operators = false:none
|
||||
csharp_style_expression_bodied_methods = true:suggestion
|
||||
csharp_style_expression_bodied_constructors = true:suggestion
|
||||
csharp_style_expression_bodied_operators = true:suggestion
|
||||
csharp_style_expression_bodied_properties = true:suggestion
|
||||
csharp_style_expression_bodied_indexers = true:none
|
||||
csharp_style_expression_bodied_accessors = true:none
|
||||
csharp_style_expression_bodied_indexers = true:suggestion
|
||||
csharp_style_expression_bodied_accessors = true:suggestion
|
||||
csharp_style_expression_bodied_lambdas = true:suggestion
|
||||
csharp_style_expression_bodied_local_functions = true:suggestion
|
||||
|
||||
# Pattern matching
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||
|
@ -103,6 +128,11 @@ csharp_style_inlined_variable_declaration = true:suggestion
|
|||
csharp_style_throw_expression = true:suggestion
|
||||
csharp_style_conditional_delegate_call = true:suggestion
|
||||
|
||||
# Other features
|
||||
csharp_style_prefer_index_operator = false:none
|
||||
csharp_style_prefer_range_operator = false:none
|
||||
csharp_style_pattern_local_over_anonymous_function = false:none
|
||||
|
||||
# Space preferences
|
||||
csharp_space_after_cast = false
|
||||
csharp_space_after_colon_in_inheritance_clause = true
|
||||
|
@ -152,4 +182,4 @@ indent_size = 2
|
|||
[*.sh]
|
||||
end_of_line = lf
|
||||
[*.{cmd, bat}]
|
||||
end_of_line = crlf
|
||||
end_of_line = crlf
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
using System;
|
||||
using Android;
|
||||
|
||||
using Android.App;
|
||||
using Android.Content.PM;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Android.OS;
|
||||
|
||||
namespace SextantSample.Droid
|
||||
|
@ -19,7 +16,7 @@ namespace SextantSample.Droid
|
|||
|
||||
base.OnCreate(bundle);
|
||||
|
||||
global::Xamarin.Forms.Forms.Init(this, bundle);
|
||||
Xamarin.Forms.Forms.Init(this, bundle);
|
||||
LoadApplication(new App());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.giusepe.SextantSample" android:installLocation="auto">
|
||||
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="28" />
|
||||
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="29" />
|
||||
<application android:label="SextantSample.Android"></application>
|
||||
</manifest>
|
||||
</manifest>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
||||
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
|
||||
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
|
||||
<TargetFrameworkVersion>v9.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v10.0</TargetFrameworkVersion>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
|
@ -74,6 +74,7 @@
|
|||
<PackageReference Include="Xamarin.Android.Support.v7.CardView" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.MediaRouter" Version="28.0.0.3" />
|
||||
<PackageReference Include="ReactiveUI.XamForms" Version="13.*" />
|
||||
<PackageReference Include="Xamarin.AndroidX.MediaRouter" Version="1.1.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="MainActivity.cs" />
|
||||
|
@ -121,4 +122,4 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.0-preview6" />
|
||||
<PackageReference Include="Citrus.Avalonia" Version="1.3.0-preview" />
|
||||
<PackageReference Include="MessageBox.Avalonia" Version="0.10.0-prev2" />
|
||||
<PackageReference Include="ReactiveUI" Version="13.*" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="**\*.xaml.cs">
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using ReactiveUI;
|
||||
using Sextant;
|
||||
|
||||
namespace SextantSample.ViewModels
|
||||
|
|
|
@ -3,7 +3,6 @@ using ReactiveUI;
|
|||
using Sextant;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Splat;
|
||||
|
||||
namespace SextantSample.ViewModels
|
||||
{
|
||||
|
@ -33,9 +32,6 @@ namespace SextantSample.ViewModels
|
|||
}
|
||||
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
Debug.WriteLine($"Destroy: {nameof(FirstModalViewModel)}");
|
||||
}
|
||||
public void Destroy() => Debug.WriteLine($"Destroy: {nameof(FirstModalViewModel)}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using ReactiveUI;
|
||||
using Sextant;
|
||||
|
@ -11,13 +10,11 @@ namespace SextantSample.ViewModels
|
|||
public class GreenViewModel : ViewModelBase, INavigable, IDestructible
|
||||
{
|
||||
public GreenViewModel(IViewStackService viewStackService)
|
||||
: base(viewStackService)
|
||||
{
|
||||
: base(viewStackService) =>
|
||||
OpenModal = ReactiveCommand
|
||||
.CreateFromObservable(() =>
|
||||
ViewStackService.PushModal(new FirstModalViewModel(viewStackService), string.Empty, false),
|
||||
outputScheduler: RxApp.MainThreadScheduler);
|
||||
}
|
||||
|
||||
public override string Id { get; } = string.Empty;
|
||||
|
||||
|
@ -32,9 +29,6 @@ namespace SextantSample.ViewModels
|
|||
public IObservable<Unit> WhenNavigatingTo(INavigationParameter parameter) =>
|
||||
Observable.Return(Unit.Default);
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
Debug.WriteLine($"Destroy: {nameof(GreenViewModel)}");
|
||||
}
|
||||
public void Destroy() => Debug.WriteLine($"Destroy: {nameof(GreenViewModel)}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using ReactiveUI;
|
||||
using Sextant;
|
||||
using Splat;
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace SextantSample.ViewModels
|
||||
{
|
||||
public static class Interactions
|
||||
{
|
||||
public static Interaction<Exception, bool> ErrorMessage = new Interaction<Exception, bool>();
|
||||
public static readonly Interaction<Exception, bool> ErrorMessage = new Interaction<Exception, bool>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using System.Windows.Input;
|
||||
using ReactiveUI;
|
||||
using Sextant;
|
||||
|
||||
namespace SextantSample.ViewModels
|
||||
{
|
||||
public class RedViewModel : ViewModelBase, IViewModel
|
||||
public class RedViewModel : ViewModelBase
|
||||
{
|
||||
public ReactiveCommand<Unit, Unit> PopModal { get; set; }
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using ReactiveUI;
|
||||
using Sextant;
|
||||
|
||||
namespace SextantSample.ViewModels
|
||||
{
|
||||
|
|
|
@ -3,7 +3,6 @@ using ReactiveUI;
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using Sextant;
|
||||
using System.Reactive.Linq;
|
||||
|
||||
namespace SextantSample.ViewModels
|
||||
{
|
||||
|
@ -28,7 +27,7 @@ namespace SextantSample.ViewModels
|
|||
outputScheduler: RxApp.MainThreadScheduler);
|
||||
|
||||
PushPage.Subscribe(x => Debug.WriteLine("PagePushed"));
|
||||
PopModal.Subscribe(x => Debug.WriteLine("PagePoped"));
|
||||
PopModal.Subscribe(x => Debug.WriteLine("PagePopped"));
|
||||
|
||||
PushPage.ThrownExceptions.Subscribe(error => Interactions.ErrorMessage.Handle(error).Subscribe());
|
||||
PopModal.ThrownExceptions.Subscribe(error => Interactions.ErrorMessage.Handle(error).Subscribe());
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace SextantSample.ViewModels
|
|||
Debugger.Break();
|
||||
}
|
||||
|
||||
RxApp.MainThreadScheduler.Schedule(() => { throw ex; });
|
||||
RxApp.MainThreadScheduler.Schedule(() => throw ex);
|
||||
}
|
||||
|
||||
public void OnError(Exception ex)
|
||||
|
@ -23,14 +23,18 @@ namespace SextantSample.ViewModels
|
|||
{
|
||||
Debugger.Break();
|
||||
}
|
||||
RxApp.MainThreadScheduler.Schedule(() => { throw ex; });
|
||||
|
||||
RxApp.MainThreadScheduler.Schedule(() => throw ex);
|
||||
}
|
||||
|
||||
public void OnCompleted()
|
||||
{
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
Debugger.Break();
|
||||
RxApp.MainThreadScheduler.Schedule(() => { throw new NotImplementedException(); });
|
||||
}
|
||||
|
||||
RxApp.MainThreadScheduler.Schedule(() => throw new NotImplementedException());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ReactiveUI" Version="12.*" />
|
||||
<PackageReference Include="ReactiveUI" Version="13.*" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Reactive;
|
||||
using ReactiveUI;
|
||||
using Sextant;
|
||||
|
||||
|
@ -9,10 +8,7 @@ namespace SextantSample.ViewModels
|
|||
{
|
||||
protected readonly IViewStackService ViewStackService;
|
||||
|
||||
protected ViewModelBase(IViewStackService viewStackService)
|
||||
{
|
||||
ViewStackService = viewStackService;
|
||||
}
|
||||
protected ViewModelBase(IViewStackService viewStackService) => ViewStackService = viewStackService;
|
||||
|
||||
public virtual string Id { get; }
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace SextantSample.UWP
|
|||
|
||||
//// Do not repeat app initialization when the Window already has content,
|
||||
//// just ensure that the window is active
|
||||
//if (rootFrame == null)
|
||||
//if (rootFrame is null)
|
||||
//{
|
||||
// // Create a Frame to act as the navigation context and navigate to the first page
|
||||
// rootFrame = new Frame();
|
||||
|
@ -83,7 +83,7 @@ namespace SextantSample.UWP
|
|||
|
||||
if (e.PrelaunchActivated == false)
|
||||
{
|
||||
//if (rootFrame.Content == null)
|
||||
//if (rootFrame.Content is null)
|
||||
//{
|
||||
// // When the navigation stack isn't restored navigate to the first page,
|
||||
// // configuring the new page by passing required information as a navigation
|
||||
|
@ -109,10 +109,7 @@ namespace SextantSample.UWP
|
|||
/// </summary>
|
||||
/// <param name="sender">The Frame which failed navigation</param>
|
||||
/// <param name="e">Details about the navigation failure</param>
|
||||
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
|
||||
{
|
||||
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
|
||||
}
|
||||
void OnNavigationFailed(object sender, NavigationFailedEventArgs e) => throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when application execution is being suspended. Application state is saved
|
||||
|
|
|
@ -12,10 +12,7 @@ namespace SextantSample.UWP.Views
|
|||
/// </summary>
|
||||
public sealed partial class GreenView : Page, IViewFor<GreenViewModel>
|
||||
{
|
||||
public GreenView()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
public GreenView() => this.InitializeComponent();
|
||||
|
||||
public static readonly DependencyProperty ViewModelProperty = DependencyProperty
|
||||
.Register(nameof(ViewModel), typeof(GreenViewModel), typeof(GreenView), null);
|
||||
|
|
|
@ -13,10 +13,7 @@ namespace SextantSample.UWP.Views
|
|||
/// </summary>
|
||||
public sealed partial class HomeView : Page, ReactiveUI.IViewFor<HomeViewModel>
|
||||
{
|
||||
public HomeView()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
public HomeView() => this.InitializeComponent();
|
||||
|
||||
public static readonly DependencyProperty ViewModelProperty = DependencyProperty
|
||||
.Register(nameof(ViewModel), typeof(HomeViewModel), typeof(HomeView), null);
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using Foundation;
|
||||
using UIKit;
|
||||
|
@ -11,7 +9,7 @@ namespace SextantSample.iOS
|
|||
// User Interface of the application, as well as listening (and optionally responding) to
|
||||
// application events from iOS.
|
||||
[Register("AppDelegate")]
|
||||
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
|
||||
public class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
|
||||
{
|
||||
//
|
||||
// This method is invoked when the application has loaded and is ready to run. In this
|
||||
|
@ -22,7 +20,7 @@ namespace SextantSample.iOS
|
|||
//
|
||||
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
|
||||
{
|
||||
global::Xamarin.Forms.Forms.Init();
|
||||
Xamarin.Forms.Forms.Init();
|
||||
LoadApplication(new App());
|
||||
|
||||
return base.FinishedLaunching(app, options);
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using Foundation;
|
||||
using UIKit;
|
||||
|
||||
namespace SextantSample.iOS
|
||||
{
|
||||
public class Application
|
||||
public static class Application
|
||||
{
|
||||
// This is the main entry point of the application.
|
||||
static void Main(string[] args)
|
||||
{
|
||||
public 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, "AppDelegate");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
|
|
|
@ -12,7 +12,7 @@ using static Sextant.Sextant;
|
|||
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
namespace SextantSample
|
||||
{
|
||||
public partial class App : Application
|
||||
public partial class App
|
||||
{
|
||||
public App()
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System;
|
||||
using System.Reactive.Concurrency;
|
||||
|
||||
using ReactiveUI;
|
||||
using Sextant;
|
||||
|
||||
using Sextant.XamForms;
|
||||
using Xamarin.Forms;
|
||||
|
||||
|
@ -12,8 +12,8 @@ namespace SextantSample.Views
|
|||
public BlueNavigationView()
|
||||
: base(RxApp.MainThreadScheduler, RxApp.TaskpoolScheduler, ViewLocator.Current)
|
||||
{
|
||||
this.BarBackgroundColor = Color.Blue;
|
||||
this.BarTextColor = Color.White;
|
||||
BarBackgroundColor = Color.Blue;
|
||||
BarTextColor = Color.White;
|
||||
}
|
||||
|
||||
public object ViewModel { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
using ReactiveUI;
|
||||
using ReactiveUI.XamForms;
|
||||
using Sextant;
|
||||
|
||||
using SextantSample.ViewModels;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace SextantSample.Views
|
||||
{
|
||||
public partial class FirstModalView : ReactiveContentPage<FirstModalViewModel>
|
||||
public partial class FirstModalView
|
||||
{
|
||||
public FirstModalView()
|
||||
{
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.XamForms;
|
||||
using SextantSample.ViewModels;
|
||||
|
||||
using SextantSample.ViewModels;
|
||||
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
using ReactiveUI;
|
||||
using ReactiveUI.XamForms;
|
||||
using Sextant;
|
||||
using System.Reactive.Disposables;
|
||||
|
||||
using ReactiveUI;
|
||||
|
||||
using SextantSample.ViewModels;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace SextantSample.Views
|
||||
{
|
||||
public partial class HomeView : ReactiveContentPage<HomeViewModel>
|
||||
public partial class HomeView
|
||||
{
|
||||
public HomeView()
|
||||
{
|
||||
|
|
|
@ -4,7 +4,7 @@ using SextantSample.ViewModels;
|
|||
|
||||
namespace SextantSample.Views
|
||||
{
|
||||
public partial class RedView : ReactiveContentPage<RedViewModel>
|
||||
public partial class RedView
|
||||
{
|
||||
public RedView()
|
||||
{
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
using ReactiveUI;
|
||||
using ReactiveUI.XamForms;
|
||||
using Sextant;
|
||||
using SextantSample.ViewModels;
|
||||
|
||||
namespace SextantSample.Views
|
||||
{
|
||||
public partial class SecondModalView : ReactiveContentPage<SecondModalViewModel>
|
||||
public partial class SecondModalView
|
||||
{
|
||||
public SecondModalView()
|
||||
{
|
||||
|
|
|
@ -21,9 +21,7 @@
|
|||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||
<!-- Optional: Include PDB in the built .nupkg -->
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
<!-- disable sourcelink on mono, to workaround https://github.com/dotnet/sourcelink/issues/155 -->
|
||||
<EnableSourceLink Condition=" '$(OS)' != 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' ">false</EnableSourceLink>
|
||||
<EnableSourceControlManagerQueries>$(EnableSourceLink)</EnableSourceControlManagerQueries>
|
||||
<WarningsAsErrors>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</WarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition="$(IsTestProject)">
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
|
||||
|
|
|
@ -15,10 +15,9 @@ namespace Sextant.Mocks
|
|||
/// </summary>
|
||||
public class NavigableViewModelMock : INavigable
|
||||
{
|
||||
private readonly string _id;
|
||||
private ISubject<Unit> _navigatedTo;
|
||||
private ISubject<Unit> _navigatingTo;
|
||||
private ISubject<Unit> _navigatedFrom;
|
||||
private readonly ISubject<Unit> _navigatedTo;
|
||||
private readonly ISubject<Unit> _navigatingTo;
|
||||
private readonly ISubject<Unit> _navigatedFrom;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NavigableViewModelMock"/> class.
|
||||
|
@ -26,7 +25,7 @@ namespace Sextant.Mocks
|
|||
/// <param name="id">The id of the page.</param>
|
||||
public NavigableViewModelMock(string? id = null)
|
||||
{
|
||||
_id = id ?? string.Empty;
|
||||
Id = id ?? string.Empty;
|
||||
_navigatedTo = new Subject<Unit>();
|
||||
_navigatedFrom = new Subject<Unit>();
|
||||
_navigatingTo = new Subject<Unit>();
|
||||
|
@ -35,7 +34,7 @@ namespace Sextant.Mocks
|
|||
/// <summary>
|
||||
/// Gets the ID of the page.
|
||||
/// </summary>
|
||||
public string Id => _id ?? nameof(NavigableViewModelMock);
|
||||
public string Id { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual IObservable<Unit> WhenNavigatedTo(INavigationParameter parameter) =>
|
||||
|
|
|
@ -17,19 +17,13 @@ namespace Sextant.Mocks
|
|||
/// </summary>
|
||||
public class NavigationViewMock : IView, IDisposable
|
||||
{
|
||||
private Subject<IViewModel> _pagePoppedSubject;
|
||||
private Stack<IViewModel> _pageStack;
|
||||
private readonly Subject<IViewModel> _pagePoppedSubject = new();
|
||||
private readonly Stack<IViewModel> _pageStack = new();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NavigationViewMock"/> class.
|
||||
/// </summary>
|
||||
public NavigationViewMock()
|
||||
{
|
||||
_pagePoppedSubject = new Subject<IViewModel>();
|
||||
_pageStack = new Stack<IViewModel>();
|
||||
|
||||
PagePopped = _pagePoppedSubject.AsObservable();
|
||||
}
|
||||
public NavigationViewMock() => PagePopped = _pagePoppedSubject.AsObservable();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IScheduler MainThreadScheduler { get; } = CurrentThreadScheduler.Instance;
|
||||
|
@ -73,7 +67,7 @@ namespace Sextant.Mocks
|
|||
{
|
||||
if (disposing)
|
||||
{
|
||||
_pagePoppedSubject?.Dispose();
|
||||
_pagePoppedSubject.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,9 +15,9 @@ namespace Sextant.Mocks
|
|||
/// </summary>
|
||||
public class NullViewModelMock : INavigable
|
||||
{
|
||||
private ISubject<Unit> _navigatedTo;
|
||||
private ISubject<Unit> _navigatingTo;
|
||||
private ISubject<Unit> _navigatedFrom;
|
||||
private readonly ISubject<Unit> _navigatedTo;
|
||||
private readonly ISubject<Unit> _navigatingTo;
|
||||
private readonly ISubject<Unit> _navigatedFrom;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NullViewModelMock"/> class.
|
||||
|
|
|
@ -4,11 +4,9 @@
|
|||
// See the LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using System.Text;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Sextant.Mocks
|
||||
|
@ -38,7 +36,7 @@ namespace Sextant.Mocks
|
|||
/// <summary>
|
||||
/// Gets the disposable.
|
||||
/// </summary>
|
||||
public CompositeDisposable Disposable { get; } = new CompositeDisposable();
|
||||
public CompositeDisposable Disposable { get; } = new();
|
||||
|
||||
/// <inheritdoc />
|
||||
public IObservable<Unit> WhenNavigatedTo(INavigationParameter parameter) => Observable.Return(Unit.Default).Do(_ => Unwrap(parameter));
|
||||
|
@ -50,10 +48,7 @@ namespace Sextant.Mocks
|
|||
public IObservable<Unit> WhenNavigatingTo(INavigationParameter parameter) => Observable.Return(Unit.Default).Do(_ => Unwrap(parameter));
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Destroy()
|
||||
{
|
||||
Disposable?.Dispose();
|
||||
}
|
||||
public void Destroy() => Disposable.Dispose();
|
||||
|
||||
private void Unwrap(INavigationParameter parameter)
|
||||
{
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<Project Sdk="MSBuild.Sdk.Extras">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0</TargetFrameworks>
|
||||
<NoWarn>$(NoWarn);1591;CA1707;SA1633;CA1034</NoWarn>
|
||||
<WarningsAsErrors>CS8625;CS8604;CS8600;CS8614;CS8603;CS8618;CS8619</WarningsAsErrors>
|
||||
<TargetFrameworks>netstandard2.0;net5.0</TargetFrameworks>
|
||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net461;uap10.0.16299</TargetFrameworks>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
|
@ -12,31 +11,4 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="..\Sextant\Sextant.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="IDestructibleMock.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="IEverything.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="NavigableViewModelMock.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="NavigatedMock.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="NavigationViewMock.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="NullViewModelMock.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="PageView.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="ParameterViewModel.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
[assembly: System.Reflection.AssemblyMetadata("RepositoryUrl", "https://github.com/reactiveui/sextant")]
|
||||
[assembly: System.Runtime.Versioning.TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName="")]
|
||||
namespace Sextant.Plugins.Popup
|
||||
{
|
||||
|
@ -52,7 +53,7 @@ namespace Sextant.Plugins.Popup
|
|||
public static readonly Xamarin.Forms.BindableProperty ViewModelProperty;
|
||||
protected SextantPopupPage() { }
|
||||
public System.IObservable<System.Reactive.Unit> BackgroundClick { get; }
|
||||
public object ViewModel { get; set; }
|
||||
public object? ViewModel { get; set; }
|
||||
protected override void OnBindingContextChanged() { }
|
||||
}
|
||||
public abstract class SextantPopupPage<TViewModel> : Sextant.Plugins.Popup.SextantPopupPage, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor<TViewModel>
|
||||
|
|
|
@ -23,23 +23,25 @@ namespace Sextant.Plugins.Popup.Tests
|
|||
[ExcludeFromCodeCoverage]
|
||||
public class ApiApprovalTests
|
||||
{
|
||||
private static readonly Regex _removeCoverletSectionRegex = new Regex(@"^namespace Coverlet\.Core\.Instrumentation\.Tracker.*?^}", RegexOptions.Singleline | RegexOptions.Multiline | RegexOptions.Compiled);
|
||||
private static readonly Regex _removeCoverletSectionRegex = new(@"^namespace Coverlet\.Core\.Instrumentation\.Tracker.*?^}", RegexOptions.Singleline | RegexOptions.Multiline | RegexOptions.Compiled);
|
||||
|
||||
/// <summary>
|
||||
/// Tests to make sure the splat project is approved.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void SextantPluginsPopup()
|
||||
{
|
||||
CheckApproval(typeof(IPopupViewStackService).Assembly);
|
||||
}
|
||||
public void SextantPluginsPopup() => CheckApproval(typeof(IPopupViewStackService).Assembly);
|
||||
|
||||
private static void CheckApproval(Assembly assembly, [CallerMemberName]string memberName = null, [CallerFilePath]string filePath = null)
|
||||
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");
|
||||
|
||||
|
@ -55,7 +57,7 @@ namespace Sextant.Plugins.Popup.Tests
|
|||
|
||||
var approvedPublicApi = File.ReadAllText(approvedFileName);
|
||||
|
||||
var receivedPublicApi = Filter(ApiGenerator.GeneratePublicApi(assembly, null));
|
||||
var receivedPublicApi = Filter(assembly.GeneratePublicApi(null));
|
||||
|
||||
if (!string.Equals(receivedPublicApi, approvedPublicApi, StringComparison.InvariantCulture))
|
||||
{
|
||||
|
|
|
@ -3,10 +3,6 @@
|
|||
// 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 ReactiveUI;
|
||||
using Rg.Plugins.Popup.Pages;
|
||||
using Sextant.Mocks;
|
||||
|
||||
namespace Sextant.Plugins.Popup.Tests
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -19,27 +19,24 @@ namespace Sextant.Plugins.Popup.Tests
|
|||
/// </summary>
|
||||
public class PopupNavigationMock : IPopupNavigation
|
||||
{
|
||||
private Stack<PopupPage> _stack;
|
||||
private readonly Stack<PopupPage> _stack;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PopupNavigationMock"/> class.
|
||||
/// </summary>
|
||||
public PopupNavigationMock()
|
||||
{
|
||||
_stack = new Stack<PopupPage>();
|
||||
}
|
||||
public PopupNavigationMock() => _stack = new Stack<PopupPage>();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public event EventHandler<PopupNavigationEventArgs> Pushing;
|
||||
public event EventHandler<PopupNavigationEventArgs>? Pushing;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public event EventHandler<PopupNavigationEventArgs> Pushed;
|
||||
public event EventHandler<PopupNavigationEventArgs>? Pushed;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public event EventHandler<PopupNavigationEventArgs> Popping;
|
||||
public event EventHandler<PopupNavigationEventArgs>? Popping;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public event EventHandler<PopupNavigationEventArgs> Popped;
|
||||
public event EventHandler<PopupNavigationEventArgs>? Popped;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IReadOnlyList<PopupPage> PopupStack => _stack.ToList();
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Sextant.Plugins.Popup.Tests
|
|||
{
|
||||
internal class PopupViewStackServiceFixture : IBuilder
|
||||
{
|
||||
private IView _view;
|
||||
private readonly IView _view;
|
||||
private IPopupNavigation _popupNavigation;
|
||||
private IViewLocator _viewLocator;
|
||||
private IViewModelFactory _viewModelFactory;
|
||||
|
@ -48,6 +48,6 @@ namespace Sextant.Plugins.Popup.Tests
|
|||
this.With(ref _viewLocator, viewLocator);
|
||||
|
||||
private PopupViewStackService Build() =>
|
||||
new PopupViewStackService(_view, _popupNavigation, _viewLocator, _viewModelFactory);
|
||||
new(_view, _popupNavigation, _viewLocator, _viewModelFactory);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,12 +4,10 @@
|
|||
// See the LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using NSubstitute;
|
||||
using NSubstitute.Extensions;
|
||||
using ReactiveUI;
|
||||
using Rg.Plugins.Popup.Contracts;
|
||||
using Rg.Plugins.Popup.Events;
|
||||
|
@ -36,7 +34,7 @@ namespace Sextant.Plugins.Popup.Tests
|
|||
public void Should_Observe_Pushing()
|
||||
{
|
||||
// Given
|
||||
PopupNavigationEvent pushing = null;
|
||||
PopupNavigationEvent? pushing = null;
|
||||
var viewModel = new NavigableViewModelMock();
|
||||
var popup = new PopupMock
|
||||
{
|
||||
|
@ -49,6 +47,11 @@ namespace Sextant.Plugins.Popup.Tests
|
|||
// 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);
|
||||
}
|
||||
|
@ -67,7 +70,7 @@ namespace Sextant.Plugins.Popup.Tests
|
|||
public async Task Should_Observe_Pushed()
|
||||
{
|
||||
// Given
|
||||
PopupNavigationEvent pushing = null;
|
||||
PopupNavigationEvent? pushing = null;
|
||||
var viewModel = new NavigableViewModelMock();
|
||||
var popup = new PopupMock
|
||||
{
|
||||
|
@ -83,6 +86,11 @@ namespace Sextant.Plugins.Popup.Tests
|
|||
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);
|
||||
}
|
||||
|
@ -100,7 +108,7 @@ namespace Sextant.Plugins.Popup.Tests
|
|||
public void Should_Observe_Pushing()
|
||||
{
|
||||
// Given
|
||||
PopupNavigationEvent pushing = null;
|
||||
PopupNavigationEvent? pushing = null;
|
||||
var viewModel = new NavigableViewModelMock();
|
||||
var popup = new PopupMock
|
||||
{
|
||||
|
@ -113,6 +121,11 @@ namespace Sextant.Plugins.Popup.Tests
|
|||
// 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);
|
||||
}
|
||||
|
@ -130,7 +143,7 @@ namespace Sextant.Plugins.Popup.Tests
|
|||
public void Should_Observe_Popped()
|
||||
{
|
||||
// Given
|
||||
PopupNavigationEvent pushing = null;
|
||||
PopupNavigationEvent? pushing = null;
|
||||
var viewModel = new NavigableViewModelMock();
|
||||
var popup = new PopupMock
|
||||
{
|
||||
|
@ -143,6 +156,11 @@ namespace Sextant.Plugins.Popup.Tests
|
|||
// 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);
|
||||
}
|
||||
|
@ -154,7 +172,7 @@ namespace Sextant.Plugins.Popup.Tests
|
|||
public void Should_Call_Destroy()
|
||||
{
|
||||
// Given
|
||||
PopupNavigationEvent pushing = null;
|
||||
PopupNavigationEvent? pushing = null;
|
||||
var viewModel = Substitute.For<IEverything>();
|
||||
var popup = new PopupMock
|
||||
{
|
||||
|
|
|
@ -20,12 +20,12 @@ namespace Sextant.Plugins.Popup
|
|||
/// <param name="isAnimated">Is the page animated.</param>
|
||||
public PopupNavigationEvent(IViewFor page, bool isAnimated)
|
||||
{
|
||||
if (page == null)
|
||||
if (page is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(page));
|
||||
}
|
||||
|
||||
if (page.ViewModel == null)
|
||||
if (page.ViewModel is null)
|
||||
{
|
||||
throw new InvalidOperationException($"{nameof(page.ViewModel)} cannot be null.");
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace Sextant.Plugins.Popup
|
|||
Pushing = Observable.FromEvent<EventHandler<PopupNavigationEventArgs>, PopupNavigationEventArgs>(
|
||||
eventHandler =>
|
||||
{
|
||||
void Handler(object sender, PopupNavigationEventArgs args) => eventHandler(args);
|
||||
void Handler(object? sender, PopupNavigationEventArgs args) => eventHandler(args);
|
||||
|
||||
return Handler;
|
||||
},
|
||||
|
@ -55,7 +55,7 @@ namespace Sextant.Plugins.Popup
|
|||
Pushed = Observable.FromEvent<EventHandler<PopupNavigationEventArgs>, PopupNavigationEventArgs>(
|
||||
eventHandler =>
|
||||
{
|
||||
void Handler(object sender, PopupNavigationEventArgs args)
|
||||
void Handler(object? sender, PopupNavigationEventArgs args)
|
||||
=> eventHandler(args);
|
||||
|
||||
return Handler;
|
||||
|
@ -67,7 +67,7 @@ namespace Sextant.Plugins.Popup
|
|||
Popping = Observable.FromEvent<EventHandler<PopupNavigationEventArgs>, PopupNavigationEventArgs>(
|
||||
eventHandler =>
|
||||
{
|
||||
void Handler(object sender, PopupNavigationEventArgs args)
|
||||
void Handler(object? sender, PopupNavigationEventArgs args)
|
||||
=> eventHandler(args);
|
||||
|
||||
return Handler;
|
||||
|
@ -79,7 +79,7 @@ namespace Sextant.Plugins.Popup
|
|||
Popped = Observable.FromEvent<EventHandler<PopupNavigationEventArgs>, PopupNavigationEventArgs>(
|
||||
eventHandler =>
|
||||
{
|
||||
void Handler(object sender, PopupNavigationEventArgs args) => eventHandler(args);
|
||||
void Handler(object? sender, PopupNavigationEventArgs args) => eventHandler(args);
|
||||
|
||||
return Handler;
|
||||
},
|
||||
|
@ -112,7 +112,7 @@ namespace Sextant.Plugins.Popup
|
|||
_popupNavigation
|
||||
.PopupStack
|
||||
.Cast<IViewFor<IViewModel>>()
|
||||
.Where(x => x != null)
|
||||
.Where(x => x is not null)
|
||||
.Select(x => x.ViewModel)
|
||||
.ToList();
|
||||
#pragma warning restore 8619
|
||||
|
@ -125,7 +125,7 @@ namespace Sextant.Plugins.Popup
|
|||
/// <inheritdoc/>
|
||||
public IObservable<Unit> PushPopup(IViewModel viewModel, string? contract = null, bool animate = true)
|
||||
{
|
||||
if (viewModel == null)
|
||||
if (viewModel is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(viewModel));
|
||||
}
|
||||
|
@ -156,12 +156,12 @@ namespace Sextant.Plugins.Popup
|
|||
string? contract = null,
|
||||
bool animate = true)
|
||||
{
|
||||
if (viewModel == null)
|
||||
if (viewModel is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(viewModel));
|
||||
}
|
||||
|
||||
if (navigationParameter == null)
|
||||
if (navigationParameter is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(navigationParameter));
|
||||
}
|
||||
|
@ -170,11 +170,11 @@ namespace Sextant.Plugins.Popup
|
|||
.Start(() => LocatePopupFor(viewModel, contract), CurrentThreadScheduler.Instance)
|
||||
.ObserveOn(CurrentThreadScheduler.Instance)
|
||||
.Do(popup =>
|
||||
popup.ViewModel.InvokeViewModelAction<INavigating>(x => x.WhenNavigatingTo(navigationParameter)))
|
||||
popup.ViewModel?.InvokeViewModelAction<INavigating>(x => x.WhenNavigatingTo(navigationParameter)))
|
||||
.Select(popup =>
|
||||
Observable
|
||||
.FromAsync(() => _popupNavigation.PushAsync(popup, animate))
|
||||
.Do(_ => popup.ViewModel.InvokeViewModelAction<INavigated>(x =>
|
||||
.Do(_ => popup.ViewModel?.InvokeViewModelAction<INavigated>(x =>
|
||||
x.WhenNavigatedTo(navigationParameter))))
|
||||
.Switch()
|
||||
.Do(_ =>
|
||||
|
@ -209,7 +209,7 @@ namespace Sextant.Plugins.Popup
|
|||
/// <inheritdoc/>
|
||||
public IObservable<Unit> RemovePopup(IViewModel viewModel, string? contract = null, bool animate = true)
|
||||
{
|
||||
if (viewModel == null)
|
||||
if (viewModel is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(viewModel));
|
||||
}
|
||||
|
@ -222,7 +222,7 @@ namespace Sextant.Plugins.Popup
|
|||
|
||||
private static void RemoveFromStackAndTick<T>(BehaviorSubject<IImmutableList<T>> stackSubject, T item)
|
||||
{
|
||||
if (stackSubject == null)
|
||||
if (stackSubject is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stackSubject));
|
||||
}
|
||||
|
@ -237,7 +237,7 @@ namespace Sextant.Plugins.Popup
|
|||
private SextantPopupPage LocatePopupFor(IViewModel viewModel, string? contract)
|
||||
{
|
||||
IViewFor? view = _viewLocator.ResolveView(viewModel, contract);
|
||||
if (view == null)
|
||||
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.");
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="MSBuild.Sdk.Extras">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFrameworks>netstandard2.0</TargetFrameworks>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<AssemblyName>Sextant.Plugins.Popup</AssemblyName>
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using ReactiveUI;
|
||||
using Rg.Plugins.Popup.Pages;
|
||||
|
@ -26,24 +25,21 @@ namespace Sextant.Plugins.Popup
|
|||
/// <summary>
|
||||
/// The view model property.
|
||||
/// </summary>
|
||||
public static readonly BindableProperty ViewModelProperty = BindableProperty.Create(
|
||||
public static new readonly BindableProperty ViewModelProperty = BindableProperty.Create(
|
||||
nameof(ViewModel),
|
||||
typeof(TViewModel),
|
||||
typeof(IViewFor<TViewModel>),
|
||||
(IViewFor<TViewModel>)null,
|
||||
null,
|
||||
BindingMode.OneWay,
|
||||
(BindableProperty.ValidateValueDelegate)null,
|
||||
new BindableProperty.BindingPropertyChangedDelegate(OnViewModelChanged),
|
||||
(BindableProperty.BindingPropertyChangingDelegate)null,
|
||||
(BindableProperty.CoerceValueDelegate)null,
|
||||
(BindableProperty.CreateDefaultValueDelegate)null);
|
||||
null,
|
||||
OnViewModelChanged);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ViewModel to display.
|
||||
/// </summary>
|
||||
public new TViewModel ViewModel
|
||||
public new TViewModel? ViewModel
|
||||
{
|
||||
get => (TViewModel)GetValue(ViewModelProperty);
|
||||
get => (TViewModel?)GetValue(ViewModelProperty);
|
||||
set => SetValue(ViewModelProperty, value);
|
||||
}
|
||||
|
||||
|
@ -51,10 +47,10 @@ namespace Sextant.Plugins.Popup
|
|||
/// Gets or sets the ViewModel corresponding to this specific View.
|
||||
/// This should be a BindableProperty if you're using XAML.
|
||||
/// </summary>
|
||||
object IViewFor.ViewModel
|
||||
object? IViewFor.ViewModel
|
||||
{
|
||||
get => ViewModel;
|
||||
set => ViewModel = (TViewModel)value;
|
||||
set => ViewModel = (TViewModel?)value;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
@ -64,10 +60,7 @@ namespace Sextant.Plugins.Popup
|
|||
ViewModel = (BindingContext as TViewModel)!;
|
||||
}
|
||||
|
||||
private static void OnViewModelChanged(BindableObject bindableObject, object oldValue, object newValue)
|
||||
{
|
||||
bindableObject.BindingContext = newValue;
|
||||
}
|
||||
private static void OnViewModelChanged(BindableObject bindableObject, object oldValue, object newValue) => bindableObject.BindingContext = newValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -82,29 +75,24 @@ namespace Sextant.Plugins.Popup
|
|||
nameof(ViewModel),
|
||||
typeof(object),
|
||||
typeof(IViewFor<object>),
|
||||
(object)null,
|
||||
null,
|
||||
BindingMode.OneWay,
|
||||
(BindableProperty.ValidateValueDelegate)null,
|
||||
new BindableProperty.BindingPropertyChangedDelegate(OnViewModelChanged),
|
||||
(BindableProperty.BindingPropertyChangingDelegate)null,
|
||||
(BindableProperty.CoerceValueDelegate)null,
|
||||
(BindableProperty.CreateDefaultValueDelegate)null);
|
||||
null,
|
||||
OnViewModelChanged);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SextantPopupPage"/> class.
|
||||
/// </summary>
|
||||
protected SextantPopupPage()
|
||||
{
|
||||
protected SextantPopupPage() =>
|
||||
BackgroundClick =
|
||||
Observable.FromEvent<EventHandler, Unit>(
|
||||
handler =>
|
||||
{
|
||||
void EventHandler(object sender, EventArgs args) => handler(Unit.Default);
|
||||
return EventHandler;
|
||||
},
|
||||
x => BackgroundClicked += x,
|
||||
x => BackgroundClicked -= x);
|
||||
}
|
||||
handler =>
|
||||
{
|
||||
void EventHandler(object? sender, EventArgs args) => handler(Unit.Default);
|
||||
return EventHandler;
|
||||
},
|
||||
x => BackgroundClicked += x,
|
||||
x => BackgroundClicked -= x);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the background click observable signal.
|
||||
|
@ -115,7 +103,7 @@ namespace Sextant.Plugins.Popup
|
|||
/// <summary>
|
||||
/// Gets or sets the ViewModel to display.
|
||||
/// </summary>
|
||||
public object ViewModel
|
||||
public object? ViewModel
|
||||
{
|
||||
get => GetValue(ViewModelProperty);
|
||||
set => SetValue(ViewModelProperty, value);
|
||||
|
@ -128,9 +116,6 @@ namespace Sextant.Plugins.Popup
|
|||
ViewModel = BindingContext;
|
||||
}
|
||||
|
||||
private static void OnViewModelChanged(BindableObject bindableObject, object oldValue, object newValue)
|
||||
{
|
||||
bindableObject.BindingContext = newValue;
|
||||
}
|
||||
private static void OnViewModelChanged(BindableObject bindableObject, object oldValue, object newValue) => bindableObject.BindingContext = newValue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
[assembly: System.Reflection.AssemblyMetadata("RepositoryUrl", "https://github.com/reactiveui/sextant")]
|
||||
[assembly: System.Runtime.Versioning.TargetFramework(".NETCoreApp,Version=v5.0", FrameworkDisplayName="")]
|
||||
namespace Sextant
|
||||
{
|
||||
public class DefaultViewModelFactory : Sextant.IViewModelFactory
|
||||
{
|
||||
public DefaultViewModelFactory() { }
|
||||
public TViewModel Create<TViewModel>(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) { }
|
||||
public static Splat.IMutableDependencyResolver RegisterView<TView, TViewModel>(this Splat.IMutableDependencyResolver dependencyResolver, string? contract = null)
|
||||
where TView : ReactiveUI.IViewFor<TViewModel>, new ()
|
||||
where TViewModel : class, Sextant.IViewModel { }
|
||||
public static Splat.IMutableDependencyResolver RegisterView<TView, TViewModel>(this Splat.IMutableDependencyResolver dependencyResolver, System.Func<ReactiveUI.IViewFor<TViewModel>> viewFactory, string? contract = null)
|
||||
where TView : ReactiveUI.IViewFor
|
||||
where TViewModel : class, Sextant.IViewModel { }
|
||||
public static Splat.IMutableDependencyResolver RegisterViewModel<TViewModel>(this Splat.IMutableDependencyResolver dependencyResolver, string? contract = null)
|
||||
where TViewModel : Sextant.IViewModel, new () { }
|
||||
public static Splat.IMutableDependencyResolver RegisterViewModel<TViewModel>(this Splat.IMutableDependencyResolver dependencyResolver, System.Func<TViewModel> viewModelFactory, string? contract = null)
|
||||
where TViewModel : class, Sextant.IViewModel { }
|
||||
public static Splat.IMutableDependencyResolver RegisterViewModel<TViewModel>(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<Sextant.IViewModelFactory> factory) { }
|
||||
public static Splat.IMutableDependencyResolver RegisterViewStackService(this Splat.IMutableDependencyResolver dependencyResolver) { }
|
||||
[System.Obsolete("Use the Func<IView, IViewModelFactory, T> variant.")]
|
||||
public static Splat.IMutableDependencyResolver RegisterViewStackService<T>(this Splat.IMutableDependencyResolver dependencyResolver, System.Func<Sextant.IView, T> factory)
|
||||
where T : Sextant.IViewStackService { }
|
||||
public static Splat.IMutableDependencyResolver RegisterViewStackService<T>(this Splat.IMutableDependencyResolver dependencyResolver, System.Func<Sextant.IView, Sextant.IViewModelFactory, T> factory)
|
||||
where T : Sextant.IViewStackService { }
|
||||
}
|
||||
public interface IDestructible
|
||||
{
|
||||
void Destroy();
|
||||
}
|
||||
public interface INavigable : Sextant.INavigated, Sextant.INavigating, Sextant.IViewModel { }
|
||||
public interface INavigated
|
||||
{
|
||||
System.IObservable<System.Reactive.Unit> WhenNavigatedFrom(Sextant.INavigationParameter parameter);
|
||||
System.IObservable<System.Reactive.Unit> WhenNavigatedTo(Sextant.INavigationParameter parameter);
|
||||
}
|
||||
public interface INavigating
|
||||
{
|
||||
System.IObservable<System.Reactive.Unit> WhenNavigatingTo(Sextant.INavigationParameter parameter);
|
||||
}
|
||||
public interface INavigationParameter : System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<string, object>>, System.Collections.Generic.IDictionary<string, object>, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, object>>, System.Collections.IEnumerable { }
|
||||
[System.Obsolete("Please use the IViewModel interface.")]
|
||||
public interface IPageViewModel : Sextant.IViewModel { }
|
||||
public interface IParameterViewStackService : Sextant.IViewStackService
|
||||
{
|
||||
System.IObservable<System.Reactive.Unit> PopPage(Sextant.INavigationParameter parameter, bool animate = true);
|
||||
System.IObservable<System.Reactive.Unit> PushModal(Sextant.INavigable navigableModal, Sextant.INavigationParameter parameter, string? contract = null, bool withNavigationPage = true);
|
||||
System.IObservable<System.Reactive.Unit> PushModal<TViewModel>(Sextant.INavigationParameter parameter, string? contract = null, bool withNavigationPage = true)
|
||||
where TViewModel : Sextant.INavigable;
|
||||
System.IObservable<System.Reactive.Unit> PushPage(Sextant.INavigable navigableViewModel, Sextant.INavigationParameter parameter, string? contract = null, bool resetStack = false, bool animate = true);
|
||||
System.IObservable<System.Reactive.Unit> PushPage<TViewModel>(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<Sextant.IViewModel?> PagePopped { get; }
|
||||
System.IObservable<System.Reactive.Unit> PopModal();
|
||||
System.IObservable<System.Reactive.Unit> PopPage(bool animate = true);
|
||||
System.IObservable<System.Reactive.Unit> PopToRootPage(bool animate = true);
|
||||
System.IObservable<System.Reactive.Unit> PushModal(Sextant.IViewModel modalViewModel, string? contract, bool withNavigationPage = true);
|
||||
System.IObservable<System.Reactive.Unit> PushPage(Sextant.IViewModel viewModel, string? contract, bool resetStack, bool animate = true);
|
||||
}
|
||||
public interface IViewModel
|
||||
{
|
||||
string Id { get; }
|
||||
}
|
||||
public interface IViewModelFactory
|
||||
{
|
||||
TViewModel Create<TViewModel>(string? contract = null)
|
||||
where TViewModel : Sextant.IViewModel;
|
||||
}
|
||||
public interface IViewStackService
|
||||
{
|
||||
System.IObservable<System.Collections.Immutable.IImmutableList<Sextant.IViewModel>> ModalStack { get; }
|
||||
System.IObservable<System.Collections.Immutable.IImmutableList<Sextant.IViewModel>> PageStack { get; }
|
||||
Sextant.IView View { get; }
|
||||
System.IObservable<System.Reactive.Unit> PopModal(bool animate = true);
|
||||
System.IObservable<System.Reactive.Unit> PopPage(bool animate = true);
|
||||
System.IObservable<System.Reactive.Unit> PopToRootPage(bool animate = true);
|
||||
System.IObservable<System.Reactive.Unit> PushModal(Sextant.IViewModel modal, string? contract = null, bool withNavigationPage = true);
|
||||
System.IObservable<System.Reactive.Unit> PushModal<TViewModel>(string? contract = null, bool withNavigationPage = true)
|
||||
where TViewModel : Sextant.IViewModel;
|
||||
System.IObservable<System.Reactive.Unit> PushPage(Sextant.INavigable page, string? contract = null, bool resetStack = false, bool animate = true);
|
||||
System.IObservable<System.Reactive.Unit> PushPage(Sextant.IViewModel page, string? contract = null, bool resetStack = false, bool animate = true);
|
||||
System.IObservable<System.Reactive.Unit> PushPage<TViewModel>(string? contract = null, bool resetStack = false, bool animate = true)
|
||||
where TViewModel : Sextant.IViewModel;
|
||||
System.IObservable<Sextant.IViewModel> TopModal();
|
||||
System.IObservable<Sextant.IViewModel> TopPage();
|
||||
}
|
||||
public class NavigationParameter : System.Collections.Generic.Dictionary<string, object>, Sextant.INavigationParameter, System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<string, object>>, System.Collections.Generic.IDictionary<string, object>, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, object>>, System.Collections.IEnumerable
|
||||
{
|
||||
public NavigationParameter() { }
|
||||
}
|
||||
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<System.Reactive.Unit> PopPage(Sextant.INavigationParameter parameter, bool animate = true) { }
|
||||
public System.IObservable<System.Reactive.Unit> PushModal(Sextant.INavigable navigableModal, Sextant.INavigationParameter parameter, string? contract = null, bool withNavigationPage = true) { }
|
||||
public System.IObservable<System.Reactive.Unit> PushModal<TViewModel>(Sextant.INavigationParameter parameter, string? contract = null, bool withNavigationPage = true)
|
||||
where TViewModel : Sextant.INavigable { }
|
||||
public System.IObservable<System.Reactive.Unit> PushPage(Sextant.INavigable navigableViewModel, Sextant.INavigationParameter parameter, string? contract = null, bool resetStack = false, bool animate = true) { }
|
||||
public System.IObservable<System.Reactive.Unit> PushPage<TViewModel>(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<T>(this object viewModel, System.Action<T> 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) { }
|
||||
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<System.Collections.Immutable.IImmutableList<Sextant.IViewModel>> ModalStack { get; }
|
||||
protected System.Reactive.Subjects.BehaviorSubject<System.Collections.Immutable.IImmutableList<Sextant.IViewModel>> ModalSubject { get; }
|
||||
protected System.Reactive.Disposables.CompositeDisposable NavigationDisposables { get; }
|
||||
public System.IObservable<System.Collections.Immutable.IImmutableList<Sextant.IViewModel>> PageStack { get; }
|
||||
protected System.Reactive.Subjects.BehaviorSubject<System.Collections.Immutable.IImmutableList<Sextant.IViewModel>> PageSubject { get; }
|
||||
public Sextant.IView View { get; }
|
||||
public void Dispose() { }
|
||||
protected virtual void Dispose(bool disposing) { }
|
||||
public System.IObservable<System.Reactive.Unit> PopModal(bool animate = true) { }
|
||||
public System.IObservable<System.Reactive.Unit> PopPage(bool animate = true) { }
|
||||
public System.IObservable<System.Reactive.Unit> PopToRootPage(bool animate = true) { }
|
||||
public System.IObservable<System.Reactive.Unit> PushModal(Sextant.IViewModel modal, string? contract = null, bool withNavigationPage = true) { }
|
||||
public System.IObservable<System.Reactive.Unit> PushModal<TViewModel>(string? contract = null, bool withNavigationPage = true)
|
||||
where TViewModel : Sextant.IViewModel { }
|
||||
public System.IObservable<System.Reactive.Unit> PushPage(Sextant.INavigable viewModel, string? contract = null, bool resetStack = false, bool animate = true) { }
|
||||
public System.IObservable<System.Reactive.Unit> PushPage(Sextant.IViewModel viewModel, string? contract = null, bool resetStack = false, bool animate = true) { }
|
||||
public System.IObservable<System.Reactive.Unit> PushPage<TViewModel>(string? contract = null, bool resetStack = false, bool animate = true)
|
||||
where TViewModel : Sextant.IViewModel { }
|
||||
public System.IObservable<Sextant.IViewModel> TopModal() { }
|
||||
public System.IObservable<Sextant.IViewModel> TopPage() { }
|
||||
protected static void AddToStackAndTick<T>(System.Reactive.Subjects.BehaviorSubject<System.Collections.Immutable.IImmutableList<T>> stackSubject, T item, bool reset) { }
|
||||
protected static void PopRootAndTick<T>(System.Reactive.Subjects.BehaviorSubject<System.Collections.Immutable.IImmutableList<T>> stackSubject, System.Reactive.Disposables.CompositeDisposable disposable) { }
|
||||
protected static T PopStackAndTick<T>(System.Reactive.Subjects.BehaviorSubject<System.Collections.Immutable.IImmutableList<T>> stackSubject) { }
|
||||
}
|
||||
}
|
||||
namespace System.Reactive.Linq
|
||||
{
|
||||
public static class SubscribeSafeExtensions { }
|
||||
public static class ToSignalExtension { }
|
||||
public static class WhereNotNullExtension { }
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
[assembly: System.Reflection.AssemblyMetadata("RepositoryUrl", "https://github.com/reactiveui/sextant")]
|
||||
[assembly: System.Runtime.Versioning.TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName="")]
|
||||
namespace Sextant
|
||||
{
|
||||
|
@ -146,11 +147,11 @@ namespace Sextant
|
|||
public sealed class ViewStackService : Sextant.ViewStackServiceBase
|
||||
{
|
||||
public ViewStackService(Sextant.IView view) { }
|
||||
public ViewStackService(Sextant.IView view, Sextant.IViewModelFactory viewModelFactory) { }
|
||||
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 ViewStackServiceBase(Sextant.IView view, Sextant.IViewModelFactory? viewModelFactory) { }
|
||||
protected Sextant.IViewModelFactory Factory { get; }
|
||||
protected Splat.IFullLogger Logger { get; }
|
||||
public System.IObservable<System.Collections.Immutable.IImmutableList<Sextant.IViewModel>> ModalStack { get; }
|
||||
|
|
|
@ -23,23 +23,25 @@ namespace Sextant.Tests
|
|||
[ExcludeFromCodeCoverage]
|
||||
public class ApiApprovalTests
|
||||
{
|
||||
private static readonly Regex _removeCoverletSectionRegex = new Regex(@"^namespace Coverlet\.Core\.Instrumentation\.Tracker.*?^}", RegexOptions.Singleline | RegexOptions.Multiline | RegexOptions.Compiled);
|
||||
private static readonly Regex _removeCoverletSectionRegex = new(@"^namespace Coverlet\.Core\.Instrumentation\.Tracker.*?^}", RegexOptions.Singleline | RegexOptions.Multiline | RegexOptions.Compiled);
|
||||
|
||||
/// <summary>
|
||||
/// Tests to make sure the splat project is approved.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Sextant()
|
||||
{
|
||||
CheckApproval(typeof(IViewStackService).Assembly);
|
||||
}
|
||||
public void Sextant() => CheckApproval(typeof(IViewStackService).Assembly);
|
||||
|
||||
private static void CheckApproval(Assembly assembly, [CallerMemberName]string memberName = null, [CallerFilePath]string filePath = null)
|
||||
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");
|
||||
|
||||
|
@ -55,7 +57,7 @@ namespace Sextant.Tests
|
|||
|
||||
var approvedPublicApi = File.ReadAllText(approvedFileName);
|
||||
|
||||
var receivedPublicApi = Filter(ApiGenerator.GeneratePublicApi(assembly, null));
|
||||
var receivedPublicApi = Filter(assembly.GeneratePublicApi(null));
|
||||
|
||||
if (!string.Equals(receivedPublicApi, approvedPublicApi, StringComparison.InvariantCulture))
|
||||
{
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace Sextant.Tests
|
|||
public void Should_Destroy()
|
||||
{
|
||||
// Given
|
||||
ParameterViewModel sut = new ParameterViewModel();
|
||||
ParameterViewModel sut = new();
|
||||
|
||||
// When
|
||||
sut.Disposable.IsDisposed.Should().BeFalse();
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace Sextant.Tests
|
|||
public void Should_Unwrap_Parameters()
|
||||
{
|
||||
// Given
|
||||
ParameterViewModel sut = new ParameterViewModel();
|
||||
ParameterViewModel sut = new();
|
||||
|
||||
// When
|
||||
sut.WhenNavigatedTo(new NavigationParameter { { "hello", "world" }, { "life", 42 } }).Subscribe();
|
||||
|
@ -45,7 +45,7 @@ namespace Sextant.Tests
|
|||
public void Should_Return_Null_If_No_Values_Provided()
|
||||
{
|
||||
// Given
|
||||
ParameterViewModel sut = new ParameterViewModel();
|
||||
ParameterViewModel sut = new();
|
||||
|
||||
// When
|
||||
sut.WhenNavigatedTo(new NavigationParameter());
|
||||
|
@ -61,7 +61,7 @@ namespace Sextant.Tests
|
|||
public void Should_Throw_If_Key_Not_Found()
|
||||
{
|
||||
// Given
|
||||
ParameterViewModel sut = new ParameterViewModel();
|
||||
ParameterViewModel sut = new();
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => sut.WhenNavigatedTo(new NavigationParameter { { "hello", "world" } }).Subscribe());
|
||||
|
@ -83,7 +83,7 @@ namespace Sextant.Tests
|
|||
public void Should_Unwrap_Parameters()
|
||||
{
|
||||
// Given
|
||||
ParameterViewModel sut = new ParameterViewModel();
|
||||
ParameterViewModel sut = new();
|
||||
|
||||
// When
|
||||
sut.WhenNavigatedFrom(new NavigationParameter { { "hello", "world" }, { "life", 42 } }).Subscribe();
|
||||
|
@ -100,7 +100,7 @@ namespace Sextant.Tests
|
|||
public void Should_Return_Null_If_No_Values_Provided()
|
||||
{
|
||||
// Given
|
||||
ParameterViewModel sut = new ParameterViewModel();
|
||||
ParameterViewModel sut = new();
|
||||
|
||||
// When
|
||||
sut.WhenNavigatedFrom(new NavigationParameter());
|
||||
|
@ -116,7 +116,7 @@ namespace Sextant.Tests
|
|||
public void Should_Throw_If_Key_Not_Found()
|
||||
{
|
||||
// Given
|
||||
ParameterViewModel sut = new ParameterViewModel();
|
||||
ParameterViewModel sut = new();
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => sut.WhenNavigatedFrom(new NavigationParameter { { "hello", "world" } }).Subscribe());
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace Sextant.Tests
|
|||
public void Should_Unwrap_Parameters()
|
||||
{
|
||||
// Given
|
||||
ParameterViewModel sut = new ParameterViewModel();
|
||||
ParameterViewModel sut = new();
|
||||
|
||||
// When
|
||||
sut.WhenNavigatingTo(new NavigationParameter { { "hello", "world" }, { "life", 42 } }).Subscribe();
|
||||
|
@ -45,7 +45,7 @@ namespace Sextant.Tests
|
|||
public void Should_Return_Null_If_No_Values_Provided()
|
||||
{
|
||||
// Given
|
||||
ParameterViewModel sut = new ParameterViewModel();
|
||||
ParameterViewModel sut = new();
|
||||
|
||||
// When
|
||||
sut.WhenNavigatingTo(new NavigationParameter());
|
||||
|
@ -61,7 +61,7 @@ namespace Sextant.Tests
|
|||
public void Should_Throw_If_Key_Not_Found()
|
||||
{
|
||||
// Given
|
||||
ParameterViewModel sut = new ParameterViewModel();
|
||||
ParameterViewModel sut = new();
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => sut.WhenNavigatingTo(new NavigationParameter { { "hello", "world" } }).Subscribe());
|
||||
|
|
|
@ -57,6 +57,6 @@ namespace Sextant.Tests
|
|||
public ParameterViewStackService WithFactory(IViewModelFactory viewModelFactory) =>
|
||||
this.With(ref _viewModelFactory, viewModelFactory);
|
||||
|
||||
private ParameterViewStackService Build() => new ParameterViewStackService(_view, _viewModelFactory);
|
||||
private ParameterViewStackService Build() => new(_view, _viewModelFactory);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,10 +28,7 @@ namespace Sextant.Tests
|
|||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TheConstructor"/> class.
|
||||
/// </summary>
|
||||
public TheConstructor()
|
||||
{
|
||||
Locator.GetLocator().UnregisterAll<IViewModelFactory>();
|
||||
}
|
||||
public TheConstructor() => Locator.GetLocator().UnregisterAll<IViewModelFactory>();
|
||||
|
||||
/// <summary>
|
||||
/// Test that the object constructed uses the static instance of ViewModelFactory.
|
||||
|
@ -40,7 +37,7 @@ namespace Sextant.Tests
|
|||
public void Should_Throw_If_View_Model_Factory_Current_Null()
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => new ParameterViewStackServiceFixture().WithFactory(null));
|
||||
var result = Record.Exception(() => new ParameterViewStackServiceFixture().WithFactory(null!));
|
||||
|
||||
// Then
|
||||
result.Should().BeOfType<ViewModelFactoryNotFoundException>();
|
||||
|
@ -56,7 +53,7 @@ namespace Sextant.Tests
|
|||
Locator.CurrentMutable.RegisterViewModelFactory();
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => new ParameterViewStackServiceFixture().WithFactory(null));
|
||||
var result = Record.Exception(() => new ParameterViewStackServiceFixture().WithFactory(null!));
|
||||
|
||||
// Then
|
||||
result.Should().BeNull();
|
||||
|
@ -81,7 +78,7 @@ namespace Sextant.Tests
|
|||
|
||||
// When
|
||||
var result =
|
||||
await Record.ExceptionAsync(async () => await sut.PushPage(null, navigationParameter))
|
||||
await Record.ExceptionAsync(async () => await sut.PushPage(null!, navigationParameter))
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// Then
|
||||
|
@ -101,7 +98,7 @@ namespace Sextant.Tests
|
|||
|
||||
// When
|
||||
var result =
|
||||
await Record.ExceptionAsync(async () => await sut.PushPage(viewModel, (INavigationParameter)null))
|
||||
await Record.ExceptionAsync(async () => await sut.PushPage(viewModel, null!))
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// Then
|
||||
|
@ -264,7 +261,7 @@ namespace Sextant.Tests
|
|||
|
||||
// When
|
||||
var result =
|
||||
await Record.ExceptionAsync(async () => await sut.PushPage<NavigableViewModelMock>(null))
|
||||
await Record.ExceptionAsync(async () => await sut.PushPage<NavigableViewModelMock>(null!))
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// Then
|
||||
|
@ -338,7 +335,7 @@ namespace Sextant.Tests
|
|||
|
||||
// When
|
||||
var result =
|
||||
await Record.ExceptionAsync(async () => await sut.PushModal(null, navigationParameter))
|
||||
await Record.ExceptionAsync(async () => await sut.PushModal(null!, navigationParameter))
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// Then
|
||||
|
@ -358,7 +355,7 @@ namespace Sextant.Tests
|
|||
|
||||
// When
|
||||
var result =
|
||||
await Record.ExceptionAsync(async () => await sut.PushModal(viewModel, null))
|
||||
await Record.ExceptionAsync(async () => await sut.PushModal(viewModel, null!))
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// Then
|
||||
|
@ -498,7 +495,7 @@ namespace Sextant.Tests
|
|||
|
||||
// When
|
||||
var result =
|
||||
await Record.ExceptionAsync(async () => await sut.PushModal<NavigableViewModelMock>(null))
|
||||
await Record.ExceptionAsync(async () => await sut.PushModal<NavigableViewModelMock>(null!))
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// Then
|
||||
|
@ -572,7 +569,7 @@ namespace Sextant.Tests
|
|||
|
||||
// When
|
||||
var result =
|
||||
await Record.ExceptionAsync(async () => await sut.PopPage(null))
|
||||
await Record.ExceptionAsync(async () => await sut.PopPage(null!))
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// Then
|
||||
|
|
|
@ -37,6 +37,6 @@ namespace Sextant.Tests
|
|||
public ViewStackServiceFixture WithFactory(IViewModelFactory viewModelFactory) =>
|
||||
this.With(ref _viewModelFactory, viewModelFactory);
|
||||
|
||||
private ViewStackService Build() => new ViewStackService(_view, _viewModelFactory);
|
||||
private ViewStackService Build() => new(_view, _viewModelFactory);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace Sextant.Tests
|
|||
return Observable.Return(Unit.Default);
|
||||
}
|
||||
|
||||
public static IObservable<Unit> PushModal(this ViewStackService viewStackService, IViewModel viewModel, string contract = null, int pages = 1)
|
||||
public static IObservable<Unit> PushModal(this ViewStackService viewStackService, IViewModel viewModel, string? contract = null, int pages = 1)
|
||||
{
|
||||
for (var i = 0; i < pages; i++)
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ namespace Sextant.Tests
|
|||
return Observable.Return(Unit.Default);
|
||||
}
|
||||
|
||||
public static IObservable<Unit> PushPage(this ViewStackService viewStackService, INavigable viewModel, string contract = null, int pages = 1)
|
||||
public static IObservable<Unit> PushPage(this ViewStackService viewStackService, INavigable viewModel, string? contract = null, int pages = 1)
|
||||
{
|
||||
for (var i = 0; i < pages; i++)
|
||||
{
|
||||
|
|
|
@ -30,10 +30,7 @@ namespace Sextant.Tests
|
|||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TheConstructor"/> class.
|
||||
/// </summary>
|
||||
public TheConstructor()
|
||||
{
|
||||
Locator.GetLocator().UnregisterAll<IViewModelFactory>();
|
||||
}
|
||||
public TheConstructor() => Locator.GetLocator().UnregisterAll<IViewModelFactory>();
|
||||
|
||||
/// <summary>
|
||||
/// Test that the object constructed uses the static instance of ViewModelFactory.
|
||||
|
@ -42,7 +39,7 @@ namespace Sextant.Tests
|
|||
public void Should_Throw_If_View_Model_Factory_Current_Null()
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => (ViewStackService)new ViewStackServiceFixture().WithFactory(null));
|
||||
var result = Record.Exception(() => (ViewStackService)new ViewStackServiceFixture().WithFactory(null!));
|
||||
|
||||
// Then
|
||||
result.Should().BeOfType<ViewModelFactoryNotFoundException>();
|
||||
|
@ -58,7 +55,7 @@ namespace Sextant.Tests
|
|||
Locator.CurrentMutable.RegisterViewModelFactory();
|
||||
|
||||
// When
|
||||
var result = Record.Exception(() => (ViewStackService)new ViewStackServiceFixture().WithFactory(null));
|
||||
var result = Record.Exception(() => (ViewStackService)new ViewStackServiceFixture().WithFactory(null!));
|
||||
|
||||
// Then
|
||||
result.Should().BeNull();
|
||||
|
@ -402,7 +399,7 @@ namespace Sextant.Tests
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests to verify the navigatino stack is cleared.
|
||||
/// Tests to verify the navigation stack is cleared.
|
||||
/// </summary>
|
||||
/// <returns>A completion notification.</returns>
|
||||
[Fact]
|
||||
|
@ -421,7 +418,7 @@ namespace Sextant.Tests
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests to verify the navigatino stack is cleared.
|
||||
/// Tests to verify the navigation stack is cleared.
|
||||
/// </summary>
|
||||
/// <returns>A completion notification.</returns>
|
||||
[Fact]
|
||||
|
@ -432,10 +429,7 @@ namespace Sextant.Tests
|
|||
ViewStackService sut = new ViewStackServiceFixture();
|
||||
await sut.PushPage(new NavigableViewModelMock(), pages: 3);
|
||||
|
||||
sut.View.PagePopped.Subscribe(_ =>
|
||||
{
|
||||
count++;
|
||||
});
|
||||
sut.View.PagePopped.Subscribe(_ => count++);
|
||||
|
||||
// When
|
||||
await sut.PopToRootPage();
|
||||
|
@ -608,7 +602,7 @@ namespace Sextant.Tests
|
|||
ViewStackService sut = new ViewStackServiceFixture();
|
||||
|
||||
// When
|
||||
var result = await Record.ExceptionAsync(async () => await sut.PushModal(null)).ConfigureAwait(false);
|
||||
var result = await Record.ExceptionAsync(async () => await sut.PushModal(null!)).ConfigureAwait(false);
|
||||
|
||||
// Then
|
||||
result.Should().BeOfType<ArgumentNullException>();
|
||||
|
@ -704,7 +698,7 @@ namespace Sextant.Tests
|
|||
ViewStackService sut = new ViewStackServiceFixture();
|
||||
|
||||
// When
|
||||
var result = await Record.ExceptionAsync(async () => await sut.PushPage(null)).ConfigureAwait(false);
|
||||
var result = await Record.ExceptionAsync(async () => await sut.PushPage(null!)).ConfigureAwait(false);
|
||||
|
||||
// Then
|
||||
result.Should().BeOfType<ArgumentNullException>().Which.ParamName.Should().Be("viewModel");
|
||||
|
@ -762,7 +756,7 @@ namespace Sextant.Tests
|
|||
await sut.PushPage(new NavigableViewModelMock());
|
||||
|
||||
// Then
|
||||
await sut.View.Received().PushPage(Arg.Any<IViewModel>(), null, false, true);
|
||||
await sut.View.Received().PushPage(Arg.Any<IViewModel>(), null, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<Project Sdk="MSBuild.Sdk.Extras">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<NoWarn>$(NoWarn);1591;CA1707;SA1633;CA1034;CA2000</NoWarn>
|
||||
<TargetFrameworks>netcoreapp3.1;net5.0</TargetFrameworks>
|
||||
<IsPackable>false</IsPackable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
|
|
|
@ -22,10 +22,7 @@ namespace Sextant.Tests
|
|||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CurrentPropertyTests"/> class.
|
||||
/// </summary>
|
||||
public CurrentPropertyTests()
|
||||
{
|
||||
Locator.CurrentMutable.UnregisterAll<IViewModelFactory>();
|
||||
}
|
||||
public CurrentPropertyTests() => Locator.CurrentMutable.UnregisterAll<IViewModelFactory>();
|
||||
|
||||
/// <summary>
|
||||
/// Should throw if the IViewFactory is not registered.
|
||||
|
@ -47,7 +44,7 @@ namespace Sextant.Tests
|
|||
public void Should_Return_View_Model_Factory()
|
||||
{
|
||||
// Given, When
|
||||
Splat.Locator.CurrentMutable.Register(() => new DefaultViewModelFactory(), typeof(IViewModelFactory));
|
||||
Locator.CurrentMutable.Register(() => new DefaultViewModelFactory(), typeof(IViewModelFactory));
|
||||
var viewModelFactory = ViewModelFactory.Current;
|
||||
|
||||
// Then
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
[assembly: System.Reflection.AssemblyMetadata("RepositoryUrl", "https://github.com/reactiveui/sextant")]
|
||||
[assembly: System.Runtime.Versioning.TargetFramework(".NETCoreApp,Version=v5.0", FrameworkDisplayName="")]
|
||||
namespace Sextant.XamForms
|
||||
{
|
||||
public static class DependencyResolverMixins
|
||||
{
|
||||
public static string NavigationView { get; }
|
||||
public static Sextant.XamForms.NavigationView? GetNavigationView(this Splat.IReadonlyDependencyResolver dependencyResolver, string? contract = null) { }
|
||||
public static Splat.IMutableDependencyResolver RegisterNavigationView(this Splat.IMutableDependencyResolver dependencyResolver) { }
|
||||
public static Splat.IMutableDependencyResolver RegisterNavigationView(this Splat.IMutableDependencyResolver dependencyResolver, System.Reactive.Concurrency.IScheduler mainThreadScheduler, System.Reactive.Concurrency.IScheduler backgroundScheduler) { }
|
||||
public static Splat.IMutableDependencyResolver RegisterNavigationView<TView>(this Splat.IMutableDependencyResolver dependencyResolver, System.Func<TView> navigationViewFactory)
|
||||
where TView : Sextant.IView { }
|
||||
}
|
||||
public class NavigationView : Xamarin.Forms.NavigationPage, Sextant.IView, Splat.IEnableLogger
|
||||
{
|
||||
public NavigationView() { }
|
||||
public NavigationView(System.Reactive.Concurrency.IScheduler mainScheduler, System.Reactive.Concurrency.IScheduler backgroundScheduler, ReactiveUI.IViewLocator viewLocator) { }
|
||||
public NavigationView(System.Reactive.Concurrency.IScheduler mainScheduler, System.Reactive.Concurrency.IScheduler backgroundScheduler, ReactiveUI.IViewLocator viewLocator, Xamarin.Forms.Page rootPage) { }
|
||||
public System.Reactive.Concurrency.IScheduler MainThreadScheduler { get; }
|
||||
public System.IObservable<Sextant.IViewModel> PagePopped { get; }
|
||||
public System.IObservable<System.Reactive.Unit> PopModal() { }
|
||||
public System.IObservable<System.Reactive.Unit> PopPage(bool animate) { }
|
||||
public System.IObservable<System.Reactive.Unit> PopToRootPage(bool animate) { }
|
||||
public System.IObservable<System.Reactive.Unit> PushModal(Sextant.IViewModel modalViewModel, string? contract, bool withNavigationPage = true) { }
|
||||
public System.IObservable<System.Reactive.Unit> PushPage(Sextant.IViewModel viewModel, string? contract, bool resetStack, bool animate) { }
|
||||
}
|
||||
public static class SextantExtensions
|
||||
{
|
||||
public static void InitializeForms(this Sextant.Sextant sextant) { }
|
||||
}
|
||||
public static class SextantHelper
|
||||
{
|
||||
[System.Obsolete("Use the Initialize method.")]
|
||||
public static Sextant.XamForms.NavigationView Initialise<TViewModel>(System.Reactive.Concurrency.IScheduler? mainThreadScheduler = null, System.Reactive.Concurrency.IScheduler? backgroundScheduler = null, ReactiveUI.IViewLocator? viewLocator = null)
|
||||
where TViewModel : class, Sextant.IViewModel { }
|
||||
[System.Obsolete("Use the dependency resolver mixins.")]
|
||||
public static Sextant.XamForms.NavigationView Initialize<TViewModel>(System.Reactive.Concurrency.IScheduler? mainThreadScheduler = null, System.Reactive.Concurrency.IScheduler? backgroundScheduler = null, ReactiveUI.IViewLocator? viewLocator = null)
|
||||
where TViewModel : class, Sextant.IViewModel { }
|
||||
[System.Obsolete("Use the dependency resolver mixins.")]
|
||||
public static void RegisterNavigation<TView, TViewModel>(System.Reactive.Concurrency.IScheduler? mainThreadScheduler = null, System.Reactive.Concurrency.IScheduler? backgroundScheduler = null, ReactiveUI.IViewLocator? viewLocator = null)
|
||||
where TView : ReactiveUI.IViewFor
|
||||
where TViewModel : class, Sextant.IViewModel { }
|
||||
[System.Obsolete("Use the dependency resolver mixins.")]
|
||||
public static void RegisterView<TView, TViewModel>(string? contract = null)
|
||||
where TView : ReactiveUI.IViewFor, new ()
|
||||
where TViewModel : class, Sextant.IViewModel { }
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
[assembly: System.Reflection.AssemblyMetadata("RepositoryUrl", "https://github.com/reactiveui/sextant")]
|
||||
[assembly: System.Runtime.Versioning.TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName="")]
|
||||
namespace Sextant.XamForms
|
||||
{
|
||||
|
|
|
@ -23,23 +23,25 @@ namespace Sextant.XamForms.Tests
|
|||
[ExcludeFromCodeCoverage]
|
||||
public class ApiApprovalTests
|
||||
{
|
||||
private static readonly Regex _removeCoverletSectionRegex = new Regex(@"^namespace Coverlet\.Core\.Instrumentation\.Tracker.*?^}", RegexOptions.Singleline | RegexOptions.Multiline | RegexOptions.Compiled);
|
||||
private static readonly Regex _removeCoverletSectionRegex = new(@"^namespace Coverlet\.Core\.Instrumentation\.Tracker.*?^}", RegexOptions.Singleline | RegexOptions.Multiline | RegexOptions.Compiled);
|
||||
|
||||
/// <summary>
|
||||
/// Tests to make sure the splat project is approved.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void SextantXamForms()
|
||||
{
|
||||
CheckApproval(typeof(NavigationView).Assembly);
|
||||
}
|
||||
public void SextantXamForms() => CheckApproval(typeof(NavigationView).Assembly);
|
||||
|
||||
private static void CheckApproval(Assembly assembly, [CallerMemberName]string memberName = null, [CallerFilePath]string filePath = null)
|
||||
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");
|
||||
|
||||
|
@ -55,7 +57,7 @@ namespace Sextant.XamForms.Tests
|
|||
|
||||
var approvedPublicApi = File.ReadAllText(approvedFileName);
|
||||
|
||||
var receivedPublicApi = Filter(ApiGenerator.GeneratePublicApi(assembly, null));
|
||||
var receivedPublicApi = Filter(assembly.GeneratePublicApi());
|
||||
|
||||
if (!string.Equals(receivedPublicApi, approvedPublicApi, StringComparison.InvariantCulture))
|
||||
{
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<Project Sdk="MSBuild.Sdk.Extras">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<NoWarn>$(NoWarn);1591;CA1707;SA1633;CA1034</NoWarn>
|
||||
<TargetFrameworks>netcoreapp3.1;net5.0</TargetFrameworks>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Sextant.XamForms.Tests
|
|||
public sealed class SextantExtensionTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests the Sextant Initalize Forms method.
|
||||
/// Tests the Sextant Initialize Forms method.
|
||||
/// </summary>
|
||||
public sealed class TheInitializeFormsMethod
|
||||
{
|
||||
|
|
|
@ -4,12 +4,9 @@
|
|||
// See the LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reactive.Concurrency;
|
||||
using System.Text;
|
||||
using ReactiveUI;
|
||||
using Sextant.XamForms;
|
||||
using Splat;
|
||||
|
||||
namespace Sextant.XamForms
|
||||
|
|
|
@ -4,9 +4,6 @@
|
|||
// See the LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Splat;
|
||||
|
||||
namespace Sextant.XamForms
|
||||
{
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
// See the LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Concurrency;
|
||||
using System.Reactive.Linq;
|
||||
|
@ -21,7 +20,6 @@ namespace Sextant.XamForms
|
|||
public class NavigationView : NavigationPage, IView, IEnableLogger
|
||||
{
|
||||
private readonly IScheduler _backgroundScheduler;
|
||||
private readonly IScheduler _mainScheduler;
|
||||
private readonly IViewLocator _viewLocator;
|
||||
private readonly IFullLogger _logger;
|
||||
|
||||
|
@ -44,21 +42,27 @@ namespace Sextant.XamForms
|
|||
: base(rootPage)
|
||||
{
|
||||
_backgroundScheduler = backgroundScheduler;
|
||||
_mainScheduler = mainScheduler;
|
||||
MainThreadScheduler = mainScheduler;
|
||||
_viewLocator = viewLocator;
|
||||
_logger = this.Log();
|
||||
|
||||
PagePopped =
|
||||
Observable
|
||||
.FromEvent<EventHandler<NavigationEventArgs>, object>(
|
||||
.FromEvent<EventHandler<NavigationEventArgs>, IViewModel>(
|
||||
handler =>
|
||||
{
|
||||
void Handler(object sender, NavigationEventArgs args) => handler(args.Page.BindingContext);
|
||||
void Handler(object? sender, NavigationEventArgs args)
|
||||
{
|
||||
if (args.Page.BindingContext is IViewModel viewModel)
|
||||
{
|
||||
handler(viewModel);
|
||||
}
|
||||
}
|
||||
|
||||
return Handler;
|
||||
},
|
||||
x => Popped += x,
|
||||
x => Popped -= x)
|
||||
.Cast<IViewModel>();
|
||||
x => Popped -= x);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -70,25 +74,31 @@ namespace Sextant.XamForms
|
|||
public NavigationView(IScheduler mainScheduler, IScheduler backgroundScheduler, IViewLocator viewLocator)
|
||||
{
|
||||
_backgroundScheduler = backgroundScheduler;
|
||||
_mainScheduler = mainScheduler;
|
||||
MainThreadScheduler = mainScheduler;
|
||||
_viewLocator = viewLocator;
|
||||
_logger = this.Log();
|
||||
|
||||
PagePopped =
|
||||
Observable
|
||||
.FromEvent<EventHandler<NavigationEventArgs>, object>(
|
||||
.FromEvent<EventHandler<NavigationEventArgs>, IViewModel>(
|
||||
handler =>
|
||||
{
|
||||
void Handler(object sender, NavigationEventArgs args) => handler(args.Page.BindingContext);
|
||||
void Handler(object? sender, NavigationEventArgs args)
|
||||
{
|
||||
if (args.Page.BindingContext is IViewModel viewModel)
|
||||
{
|
||||
handler(viewModel);
|
||||
}
|
||||
}
|
||||
|
||||
return Handler;
|
||||
},
|
||||
x => Popped += x,
|
||||
x => Popped -= x)
|
||||
.Cast<IViewModel>();
|
||||
x => Popped -= x);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IScheduler MainThreadScheduler => _mainScheduler;
|
||||
public IScheduler MainThreadScheduler { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IObservable<IViewModel> PagePopped { get; }
|
||||
|
@ -99,7 +109,7 @@ namespace Sextant.XamForms
|
|||
.PopModalAsync()
|
||||
.ToObservable()
|
||||
.Select(_ => Unit.Default)
|
||||
.ObserveOn(_mainScheduler); // XF completes the pop operation on a background thread :/
|
||||
.ObserveOn(MainThreadScheduler); // XF completes the pop operation on a background thread :/
|
||||
|
||||
/// <inheritdoc />
|
||||
public IObservable<Unit> PopPage(bool animate) =>
|
||||
|
@ -107,7 +117,7 @@ namespace Sextant.XamForms
|
|||
.PopAsync(animate)
|
||||
.ToObservable()
|
||||
.Select(_ => Unit.Default)
|
||||
.ObserveOn(_mainScheduler); // XF completes the pop operation on a background thread :/
|
||||
.ObserveOn(MainThreadScheduler); // XF completes the pop operation on a background thread :/
|
||||
|
||||
/// <inheritdoc />
|
||||
public IObservable<Unit> PopToRootPage(bool animate) =>
|
||||
|
@ -115,7 +125,7 @@ namespace Sextant.XamForms
|
|||
.PopToRootAsync(animate)
|
||||
.ToObservable()
|
||||
.Select(_ => Unit.Default)
|
||||
.ObserveOn(_mainScheduler);
|
||||
.ObserveOn(MainThreadScheduler);
|
||||
|
||||
/// <inheritdoc />
|
||||
public IObservable<Unit> PushModal(IViewModel modalViewModel, string? contract, bool withNavigationPage = true) =>
|
||||
|
@ -125,12 +135,7 @@ namespace Sextant.XamForms
|
|||
{
|
||||
var page = LocatePageFor(modalViewModel, contract);
|
||||
SetPageTitle(page, modalViewModel.Id);
|
||||
if (withNavigationPage)
|
||||
{
|
||||
return new NavigationPage(page);
|
||||
}
|
||||
|
||||
return page;
|
||||
return withNavigationPage ? new NavigationPage(page) : page;
|
||||
},
|
||||
CurrentThreadScheduler.Instance)
|
||||
.ObserveOn(CurrentThreadScheduler.Instance)
|
||||
|
@ -180,11 +185,17 @@ namespace Sextant.XamForms
|
|||
.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 == null)
|
||||
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.");
|
||||
}
|
||||
|
@ -198,12 +209,5 @@ namespace Sextant.XamForms
|
|||
|
||||
return page;
|
||||
}
|
||||
|
||||
private void SetPageTitle(Page page, string resourceKey)
|
||||
{
|
||||
// var title = Localize.GetString(resourceKey);
|
||||
// TODO: ensure resourceKey isn't null and is localized.
|
||||
page.Title = resourceKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
<Project Sdk="MSBuild.Sdk.Extras">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFrameworks>netstandard2.0;net5.0</TargetFrameworks>
|
||||
<AssemblyName>Sextant.XamForms</AssemblyName>
|
||||
<RootNamespace>Sextant</RootNamespace>
|
||||
<RootNamespace>Sextant.XamForms</RootNamespace>
|
||||
<PackageId>Sextant.XamForms</PackageId>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<WarningsAsErrors>CS8625;CS8604;CS8600;CS8614;CS8603;CS8618;CS8619</WarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ReactiveUI" Version="12.*" />
|
||||
<PackageReference Include="ReactiveUI" Version="13.*" />
|
||||
<PackageReference Include="System.Collections.Immutable" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) ">
|
||||
<PackageReference Include="Xamarin.Forms" Version="4.5.*" />
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Xamarin.Forms" Version="4.6.*" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=mixins/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
|
@ -24,10 +24,8 @@ namespace Sextant.XamForms
|
|||
[Obsolete("Use the dependency resolver mixins.")]
|
||||
public static void RegisterView<TView, TViewModel>(string? contract = null)
|
||||
where TView : IViewFor, new()
|
||||
where TViewModel : class, IViewModel
|
||||
{
|
||||
where TViewModel : class, IViewModel =>
|
||||
Locator.CurrentMutable.Register(() => new TView(), typeof(IViewFor<TViewModel>), contract);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a value for navigation.
|
||||
|
@ -72,9 +70,8 @@ namespace Sextant.XamForms
|
|||
var viewStackService = new ViewStackService(navigationView);
|
||||
|
||||
Locator.CurrentMutable.Register<IViewStackService>(() => viewStackService);
|
||||
var instance = Activator.CreateInstance(typeof(TViewModel), viewStackService) as TViewModel;
|
||||
|
||||
if (instance == null)
|
||||
if (!(Activator.CreateInstance(typeof(TViewModel), viewStackService) is TViewModel instance))
|
||||
{
|
||||
throw new InvalidOperationException($"Could not initialize a view for view model {typeof(TViewModel)}");
|
||||
}
|
||||
|
@ -94,9 +91,7 @@ namespace Sextant.XamForms
|
|||
/// <returns>The navigation view.</returns>
|
||||
[Obsolete("Use the " + nameof(Initialize) + " method.")]
|
||||
public static NavigationView Initialise<TViewModel>(IScheduler? mainThreadScheduler = null, IScheduler? backgroundScheduler = null, IViewLocator? viewLocator = null)
|
||||
where TViewModel : class, IViewModel
|
||||
{
|
||||
return Initialize<TViewModel>(mainThreadScheduler, backgroundScheduler, viewLocator);
|
||||
}
|
||||
where TViewModel : class, IViewModel =>
|
||||
Initialize<TViewModel>(mainThreadScheduler, backgroundScheduler, viewLocator);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace Sextant.IOS.Runner
|
|||
/// <summary>
|
||||
/// The iOS application.
|
||||
/// </summary>
|
||||
public class Application
|
||||
public static class Application
|
||||
{
|
||||
// This is the main entry point of the application.
|
||||
|
||||
|
@ -19,12 +19,11 @@ namespace Sextant.IOS.Runner
|
|||
/// Defines the entry point of the application.
|
||||
/// </summary>
|
||||
/// <param name="args">The arguments.</param>
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
private 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, "AppDelegate");
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore SA1649 // File name should match first type name
|
||||
|
|
|
@ -18,10 +18,7 @@ namespace Sextant.IOS.Runner
|
|||
/// Initializes a new instance of the <see cref="PageViewModelMock"/> class.
|
||||
/// </summary>
|
||||
/// <param name="id">The id of the page.</param>
|
||||
public PageViewModelMock(string id = null)
|
||||
{
|
||||
_id = id;
|
||||
}
|
||||
public PageViewModelMock(string id = null) => _id = id;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ID of the page.
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
is_global = true
|
||||
build_property.TargetFramework =
|
||||
build_property.TargetPlatformMinVersion =
|
||||
build_property.UsingMicrosoftNETSdkWeb =
|
||||
build_property.ProjectTypeGuids = {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
|
||||
build_property.PublishSingleFile =
|
||||
build_property.IncludeAllContentForSelfExtract =
|
||||
build_property._SupportedPlatformList =
|
|
@ -11,6 +11,7 @@
|
|||
<IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
|
||||
<AssemblyName>Blank</AssemblyName>
|
||||
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
|
|
@ -17,9 +17,6 @@ namespace Sextant.IOS.Runner
|
|||
internal class TestViewLocator
|
||||
: IViewLocator
|
||||
{
|
||||
public IViewFor ResolveView<T>(T viewModel, string contract = null)
|
||||
{
|
||||
return new PageUiViewController();
|
||||
}
|
||||
public IViewFor ResolveView<T>(T viewModel, string contract = null) => new PageUiViewController();
|
||||
}
|
||||
}
|
||||
|
|
1042
src/Sextant.sln
1042
src/Sextant.sln
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -38,7 +38,7 @@ namespace Sextant
|
|||
IObservable<Unit> PopPage(bool animate = true);
|
||||
|
||||
/// <summary>
|
||||
/// Pops the the root page.
|
||||
/// Pops the root page.
|
||||
/// </summary>
|
||||
/// <param name="animate">if set to <c>true</c> [animate].</param>
|
||||
/// <returns>An observable that signals when the pop has been completed.</returns>
|
||||
|
|
|
@ -83,7 +83,7 @@ namespace Sextant
|
|||
}
|
||||
|
||||
IView view = Locator.Current.GetService<IView>(NavigationView);
|
||||
dependencyResolver.RegisterLazySingleton<T>(() => factory(view));
|
||||
dependencyResolver.RegisterLazySingleton(() => factory(view));
|
||||
return dependencyResolver;
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ namespace Sextant
|
|||
|
||||
IView view = Locator.Current.GetService<IView>(NavigationView);
|
||||
IViewModelFactory viewModelFactory = Locator.Current.GetService<IViewModelFactory>();
|
||||
dependencyResolver.RegisterLazySingleton<T>(() => factory(view, viewModelFactory));
|
||||
dependencyResolver.RegisterLazySingleton(() => factory(view, viewModelFactory));
|
||||
return dependencyResolver;
|
||||
}
|
||||
|
||||
|
@ -158,7 +158,7 @@ namespace Sextant
|
|||
/// <typeparam name="TViewModel">The type of the view model.</typeparam>
|
||||
/// <param name="dependencyResolver">The dependency resolver.</param>
|
||||
/// <param name="contract">The contract.</param>
|
||||
/// <returns>The dependencyResovler.</returns>
|
||||
/// <returns>The dependency resolver to use.</returns>
|
||||
public static IMutableDependencyResolver RegisterView<TView, TViewModel>(this IMutableDependencyResolver dependencyResolver, string? contract = null)
|
||||
where TView : IViewFor<TViewModel>, new()
|
||||
where TViewModel : class, IViewModel
|
||||
|
|
|
@ -32,12 +32,12 @@ namespace Sextant
|
|||
bool resetStack = false,
|
||||
bool animate = true)
|
||||
{
|
||||
if (navigableViewModel == null)
|
||||
if (navigableViewModel is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(navigableViewModel));
|
||||
}
|
||||
|
||||
if (parameter == null)
|
||||
if (parameter is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(parameter));
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ namespace Sextant
|
|||
navigableViewModel
|
||||
.WhenNavigatingTo(parameter)
|
||||
.ObserveOn(View.MainThreadScheduler)
|
||||
.Subscribe(navigating =>
|
||||
.Subscribe(_ =>
|
||||
Logger.Debug(
|
||||
$"Called `WhenNavigatingTo` on '{navigableViewModel.Id}' passing parameter {parameter}"));
|
||||
|
||||
|
@ -59,19 +59,19 @@ namespace Sextant
|
|||
navigableViewModel
|
||||
.WhenNavigatedTo(parameter)
|
||||
.ObserveOn(View.MainThreadScheduler)
|
||||
.Subscribe(navigated => Logger.Debug($"Called `WhenNavigatedTo` on '{navigableViewModel.Id}' passing parameter {parameter}"));
|
||||
.Subscribe(_ => Logger.Debug($"Called `WhenNavigatedTo` on '{navigableViewModel.Id}' passing parameter {parameter}"));
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IObservable<Unit> PushModal(INavigable navigableModal, INavigationParameter parameter, string? contract = null, bool withNavigationPage = true)
|
||||
{
|
||||
if (navigableModal == null)
|
||||
if (navigableModal is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(navigableModal));
|
||||
}
|
||||
|
||||
if (parameter == null)
|
||||
if (parameter is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(parameter));
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ namespace Sextant
|
|||
navigableModal
|
||||
.WhenNavigatingTo(parameter)
|
||||
.ObserveOn(View.MainThreadScheduler)
|
||||
.Subscribe(navigating =>
|
||||
.Subscribe(_ =>
|
||||
Logger.Debug($"Called `WhenNavigatingTo` on '{navigableModal.Id}' passing parameter {parameter}"));
|
||||
|
||||
return View
|
||||
|
@ -92,7 +92,7 @@ namespace Sextant
|
|||
navigableModal
|
||||
.WhenNavigatedTo(parameter)
|
||||
.ObserveOn(View.MainThreadScheduler)
|
||||
.Subscribe(navigated => Logger.Debug($"Called `WhenNavigatedTo` on '{navigableModal.Id}' passing parameter {parameter}"));
|
||||
.Subscribe(_ => Logger.Debug($"Called `WhenNavigatedTo` on '{navigableModal.Id}' passing parameter {parameter}"));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -115,31 +115,30 @@ namespace Sextant
|
|||
/// <inheritdoc />
|
||||
public IObservable<Unit> PopPage(INavigationParameter parameter, bool animate = true)
|
||||
{
|
||||
if (parameter == null)
|
||||
if (parameter is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(parameter));
|
||||
}
|
||||
|
||||
IViewModel poppedPage = TopPage().FirstOrDefaultAsync().Wait();
|
||||
IViewModel? poppedPage = TopPage().FirstOrDefaultAsync().Wait();
|
||||
return View
|
||||
.PopPage(animate)
|
||||
.Do(_ =>
|
||||
{
|
||||
poppedPage
|
||||
.InvokeViewModelAction<INavigable>(x =>
|
||||
poppedPage?.InvokeViewModelAction<INavigable>(x =>
|
||||
x.WhenNavigatedFrom(parameter)
|
||||
.ObserveOn(View.MainThreadScheduler)
|
||||
.Subscribe(navigatedFrom =>
|
||||
.Subscribe(_ =>
|
||||
Logger.Debug($"Called `WhenNavigatedFrom` on '{poppedPage.Id}' passing parameter {parameter}")))
|
||||
.InvokeViewModelAction<IDestructible>(x => x.Destroy());
|
||||
|
||||
IViewModel topPage = TopPage().FirstOrDefaultAsync().Wait();
|
||||
IViewModel? topPage = TopPage().FirstOrDefaultAsync().Wait();
|
||||
if (topPage is INavigated navigated)
|
||||
{
|
||||
navigated
|
||||
.WhenNavigatedTo(parameter)
|
||||
.ObserveOn(View.MainThreadScheduler)
|
||||
.Subscribe(navigatedTo =>
|
||||
.Subscribe(_ =>
|
||||
Logger.Debug($"Called `WhenNavigatedTo` passing parameter {parameter}"));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -22,17 +22,19 @@ namespace Sextant
|
|||
public static object InvokeViewModelAction<T>(this object viewModel, Action<T> action)
|
||||
where T : class
|
||||
{
|
||||
if (action == null)
|
||||
if (action is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(action));
|
||||
}
|
||||
|
||||
if (viewModel is IViewModel element)
|
||||
if (viewModel is not IViewModel element)
|
||||
{
|
||||
if (element is T viewModelAsT)
|
||||
{
|
||||
action(viewModelAsT);
|
||||
}
|
||||
return viewModel;
|
||||
}
|
||||
|
||||
if (element is T viewModelAsT)
|
||||
{
|
||||
action(viewModelAsT);
|
||||
}
|
||||
|
||||
return viewModel;
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace Sextant
|
|||
/// </summary>
|
||||
/// <param name="view">The view.</param>
|
||||
public ViewStackService(IView view)
|
||||
: this(view, null!)
|
||||
: this(view, null)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ namespace Sextant
|
|||
/// </summary>
|
||||
/// <param name="view">The view.</param>
|
||||
/// <param name="viewModelFactory">The view model factory.</param>
|
||||
public ViewStackService(IView view, IViewModelFactory viewModelFactory)
|
||||
public ViewStackService(IView view, IViewModelFactory? viewModelFactory)
|
||||
: base(view, viewModelFactory)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace Sextant
|
|||
/// </summary>
|
||||
/// <param name="view">The view.</param>
|
||||
/// <param name="viewModelFactory">The view model factory.</param>
|
||||
protected ViewStackServiceBase(IView view, IViewModelFactory viewModelFactory)
|
||||
protected ViewStackServiceBase(IView view, IViewModelFactory? viewModelFactory)
|
||||
{
|
||||
Logger = this.Log();
|
||||
View = view ?? throw new ArgumentNullException(nameof(view));
|
||||
|
@ -66,12 +66,12 @@ namespace Sextant
|
|||
/// <summary>
|
||||
/// Gets the current view on the stack.
|
||||
/// </summary>
|
||||
public IView View { get; private set; }
|
||||
public IView View { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the logger.
|
||||
/// </summary>
|
||||
protected IFullLogger Logger { get; private set; }
|
||||
protected IFullLogger Logger { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the view model factory.
|
||||
|
@ -81,17 +81,17 @@ namespace Sextant
|
|||
/// <summary>
|
||||
/// Gets the modal subject.
|
||||
/// </summary>
|
||||
protected BehaviorSubject<IImmutableList<IViewModel>> ModalSubject { get; private set; }
|
||||
protected BehaviorSubject<IImmutableList<IViewModel>> ModalSubject { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the page subject.
|
||||
/// </summary>
|
||||
protected BehaviorSubject<IImmutableList<IViewModel>> PageSubject { get; private set; }
|
||||
protected BehaviorSubject<IImmutableList<IViewModel>> PageSubject { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the navigation disposables.
|
||||
/// </summary>
|
||||
protected CompositeDisposable NavigationDisposables { get; } = new CompositeDisposable();
|
||||
protected CompositeDisposable NavigationDisposables { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Pops the <see cref="INavigable" /> off the stack.
|
||||
|
@ -110,10 +110,8 @@ namespace Sextant
|
|||
public IObservable<Unit> PopPage(bool animate = true)
|
||||
{
|
||||
var top = TopPage().Wait();
|
||||
return View.PopPage(animate).Do(_ =>
|
||||
{
|
||||
top.InvokeViewModelAction<IDestructible>(x => x.Destroy());
|
||||
});
|
||||
return View.PopPage(animate)
|
||||
.Do(_ => top.InvokeViewModelAction<IDestructible>(x => x.Destroy()));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@ -124,7 +122,7 @@ namespace Sextant
|
|||
/// <inheritdoc />
|
||||
public IObservable<Unit> PushModal(IViewModel modal, string? contract = null, bool withNavigationPage = true)
|
||||
{
|
||||
if (modal == null)
|
||||
if (modal is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(modal));
|
||||
}
|
||||
|
@ -158,7 +156,7 @@ namespace Sextant
|
|||
/// <inheritdoc />
|
||||
public IObservable<Unit> PushPage(IViewModel viewModel, string? contract = null, bool resetStack = false, bool animate = true)
|
||||
{
|
||||
if (viewModel == null)
|
||||
if (viewModel is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(viewModel));
|
||||
}
|
||||
|
@ -214,14 +212,7 @@ namespace Sextant
|
|||
|
||||
var stack = stackSubject.Value;
|
||||
|
||||
if (reset)
|
||||
{
|
||||
stack = new[] { item }.ToImmutableList();
|
||||
}
|
||||
else
|
||||
{
|
||||
stack = stack.Add(item);
|
||||
}
|
||||
stack = reset ? new[] { item }.ToImmutableList() : stack.Add(item);
|
||||
|
||||
stackSubject.OnNext(stack);
|
||||
}
|
||||
|
@ -263,14 +254,14 @@ namespace Sextant
|
|||
protected static void PopRootAndTick<T>(BehaviorSubject<IImmutableList<T>> stackSubject, CompositeDisposable disposable)
|
||||
{
|
||||
IImmutableList<T> poppedStack = ImmutableList<T>.Empty;
|
||||
if (stackSubject == null || stackSubject.Value.Count == 0)
|
||||
if (stackSubject is null || stackSubject.Value.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException("Stack is empty.");
|
||||
}
|
||||
|
||||
stackSubject
|
||||
.Take(1)
|
||||
.Where(stack => stack != null)
|
||||
.Where(stack => stack is not null)
|
||||
.Subscribe(stack =>
|
||||
{
|
||||
if (stack.Count > 1)
|
||||
|
@ -279,7 +270,7 @@ namespace Sextant
|
|||
|
||||
foreach (T popped in stack.RemoveRange(poppedStack).Reverse())
|
||||
{
|
||||
if (popped == null)
|
||||
if (popped is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2019 .NET Foundation and Contributors. All rights reserved.
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Sextant
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions methods to setup the <see cref="Sextant"/> instance.
|
||||
/// </summary>
|
||||
public static class SextantExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the specified sextant.
|
||||
/// </summary>
|
||||
/// <param name="sextant">The sextant.</param>
|
||||
public static void Initialize(this Sextant sextant)
|
||||
{
|
||||
if (sextant is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(sextant));
|
||||
}
|
||||
|
||||
sextant.MutableLocator.RegisterViewStackService();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,10 +4,6 @@
|
|||
// See the LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.UI.Xaml;
|
||||
|
||||
namespace Sextant
|
||||
|
@ -25,10 +21,7 @@ namespace Sextant
|
|||
/// </summary>
|
||||
public string? DeviceFamily
|
||||
{
|
||||
get
|
||||
{
|
||||
return _queriedDeviceFamily;
|
||||
}
|
||||
get => _queriedDeviceFamily;
|
||||
|
||||
set
|
||||
{
|
||||
|
|
|
@ -4,10 +4,8 @@
|
|||
// See the LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reactive.Concurrency;
|
||||
using System.Text;
|
||||
using ReactiveUI;
|
||||
using Splat;
|
||||
|
||||
|
@ -138,7 +136,7 @@ namespace Sextant
|
|||
throw new ArgumentNullException(nameof(dependencyResolver));
|
||||
}
|
||||
|
||||
var uwpViewTypeResolver = Locator.Current.GetService<ViewTypeResolver>(contract);
|
||||
var uwpViewTypeResolver = dependencyResolver.GetService<ViewTypeResolver>(contract);
|
||||
return uwpViewTypeResolver.ResolveViewType<TViewModel>();
|
||||
}
|
||||
|
||||
|
@ -163,8 +161,7 @@ namespace Sextant
|
|||
throw new ArgumentNullException(nameof(viewModel));
|
||||
}
|
||||
|
||||
var vm = viewModel;
|
||||
var uwpViewTypeResolver = Locator.Current.GetService<ViewTypeResolver>(contract);
|
||||
var uwpViewTypeResolver = dependencyResolver.GetService<ViewTypeResolver>(contract);
|
||||
return uwpViewTypeResolver.ResolveViewType<TViewModel>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,6 @@
|
|||
// See the LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reactive.Concurrency;
|
||||
using System.Text;
|
||||
using Splat;
|
||||
|
||||
namespace Sextant
|
||||
{
|
||||
|
|
|
@ -14,15 +14,7 @@ namespace Sextant
|
|||
/// </summary>
|
||||
public class ViewTypeResolver
|
||||
{
|
||||
private Dictionary<(string vmTypeName, string? contract), Type> _typeDictionary;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ViewTypeResolver"/> class.
|
||||
/// </summary>
|
||||
public ViewTypeResolver()
|
||||
{
|
||||
_typeDictionary = new Dictionary<(string vmTypeName, string? contract), Type>();
|
||||
}
|
||||
private readonly Dictionary<(string VmTypeName, string? Contract), Type> _typeDictionary = new();
|
||||
|
||||
/// <summary>
|
||||
/// Register view Type with viewmodel Type.
|
||||
|
@ -51,12 +43,9 @@ namespace Sextant
|
|||
public Type? ResolveViewType<TViewModel>(string? contract = null)
|
||||
where TViewModel : class
|
||||
{
|
||||
if (_typeDictionary.ContainsKey((typeof(TViewModel).AssemblyQualifiedName, contract)))
|
||||
{
|
||||
return _typeDictionary[(typeof(TViewModel).AssemblyQualifiedName, contract)];
|
||||
}
|
||||
_typeDictionary.TryGetValue((typeof(TViewModel).AssemblyQualifiedName, contract), out var value);
|
||||
|
||||
return null;
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -72,12 +61,9 @@ namespace Sextant
|
|||
throw new ArgumentNullException(nameof(viewModelType));
|
||||
}
|
||||
|
||||
if (_typeDictionary.ContainsKey((viewModelType.AssemblyQualifiedName, contract)))
|
||||
{
|
||||
return _typeDictionary[(viewModelType.AssemblyQualifiedName, contract)];
|
||||
}
|
||||
_typeDictionary.TryGetValue((viewModelType.AssemblyQualifiedName, contract), out var value);
|
||||
|
||||
return null;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,22 +5,18 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Concurrency;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Threading.Tasks;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
|
||||
using ReactiveUI;
|
||||
|
||||
using Splat;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
|
||||
using Windows.UI.Core;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls.Primitives;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Animation;
|
||||
|
@ -31,23 +27,21 @@ namespace Sextant
|
|||
/// <summary>
|
||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
public partial class NavigationView : Page, IView, IEnableLogger
|
||||
public partial class NavigationView : IView, IEnableLogger
|
||||
{
|
||||
/// <summary>
|
||||
/// A depedendency property for the back button.
|
||||
/// A dependency property for the back button.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsBackButtonVisibleProperty =
|
||||
DependencyProperty.Register("IsBackButtonVisible", typeof(bool), typeof(NavigationView), new PropertyMetadata(true));
|
||||
|
||||
private readonly IScheduler _backgroundScheduler;
|
||||
private readonly IScheduler _mainScheduler;
|
||||
private readonly IViewLocator _viewLocator;
|
||||
private IFullLogger _logger;
|
||||
private readonly IFullLogger _logger;
|
||||
private readonly Stack<IViewModel?> _mirroredPageStack;
|
||||
private readonly Stack<IViewModel?> _mirroredModalStack;
|
||||
|
||||
private ContentDialog? _contentDialog;
|
||||
private IViewModel? _lastPoppedViewModel;
|
||||
private Stack<IViewModel?> _mirroredPageStack;
|
||||
private Stack<IViewModel?> _mirroredModalStack;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NavigationView"/> class.
|
||||
|
@ -69,8 +63,8 @@ namespace Sextant
|
|||
|
||||
_logger = this.Log();
|
||||
|
||||
_backgroundScheduler = backgroundScheduler;
|
||||
_mainScheduler = mainScheduler;
|
||||
BackgroundScheduler = backgroundScheduler;
|
||||
MainThreadScheduler = mainScheduler;
|
||||
_viewLocator = viewLocator;
|
||||
|
||||
_mirroredPageStack = new Stack<IViewModel?>();
|
||||
|
@ -80,28 +74,14 @@ namespace Sextant
|
|||
|
||||
PagePopped = Observable
|
||||
.FromEvent<NavigatedEventHandler, NavigationEventArgs>(
|
||||
handler =>
|
||||
{
|
||||
return (sender, e) => handler(e);
|
||||
},
|
||||
handler => (_, e) => handler(e),
|
||||
x => mainFrame.Navigated += x,
|
||||
x => mainFrame.Navigated -= x)
|
||||
.Do(args =>
|
||||
{
|
||||
if (mainFrame.CanGoBack)
|
||||
{
|
||||
IsBackButtonVisible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsBackButtonVisible = false;
|
||||
}
|
||||
})
|
||||
.Do(_ => IsBackButtonVisible = mainFrame.CanGoBack)
|
||||
.Where(ep => ep.NavigationMode == NavigationMode.Back)
|
||||
.Select(ep =>
|
||||
{
|
||||
var view = ep.Content as IViewFor;
|
||||
if (view == null)
|
||||
if (!(ep.Content is IViewFor view))
|
||||
{
|
||||
_logger.Debug($"The view ({ep.Content.GetType()}) does not implement IViewFor<>. Cannot set ViewModel from a back navigation.");
|
||||
}
|
||||
|
@ -115,7 +95,7 @@ namespace Sextant
|
|||
// But we want the view that was just removed. We need to send the old view's viewmodel to IViewStackService so that the ViewModel can be removed from the stack.
|
||||
return _lastPoppedViewModel;
|
||||
})
|
||||
.Where(x => x != null);
|
||||
.Where(x => x is not null);
|
||||
|
||||
BackRequested.Subscribe();
|
||||
}
|
||||
|
@ -128,35 +108,37 @@ namespace Sextant
|
|||
get
|
||||
{
|
||||
var popups = VisualTreeHelper.GetOpenPopups(Window.Current);
|
||||
return popups.FirstOrDefault(x => x.Child is ContentDialog) != null;
|
||||
return popups.FirstOrDefault(x => x.Child is ContentDialog) is not null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the background scheduler.
|
||||
/// </summary>
|
||||
public IScheduler BackgroundScheduler { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the default back button is visible.
|
||||
/// </summary>
|
||||
public bool IsBackButtonVisible
|
||||
{
|
||||
get { return (bool)GetValue(IsBackButtonVisibleProperty); }
|
||||
set { SetValue(IsBackButtonVisibleProperty, value); }
|
||||
get => (bool)GetValue(IsBackButtonVisibleProperty);
|
||||
set => SetValue(IsBackButtonVisibleProperty, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IScheduler MainThreadScheduler => _mainScheduler;
|
||||
public IScheduler MainThreadScheduler { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IObservable<IViewModel?> PagePopped { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets combined backrequested observable from system, backbutton, and xbox controller sources.
|
||||
/// Gets combined back requested observable from system, back button, and xbox controller sources.
|
||||
/// </summary>
|
||||
public IObservable<Unit> BackRequested => Observable.Merge(
|
||||
Observable
|
||||
.FromEvent<EventHandler<BackRequestedEventArgs>, BackRequestedEventArgs>(
|
||||
handler =>
|
||||
{
|
||||
return (_, e) => handler(e);
|
||||
},
|
||||
handler => (_, e) => handler(e),
|
||||
x => SystemNavigationManager.GetForCurrentView().BackRequested += x,
|
||||
x => SystemNavigationManager.GetForCurrentView().BackRequested -= x)
|
||||
.Do(ev =>
|
||||
|
@ -170,10 +152,12 @@ namespace Sextant
|
|||
.Select(_ => Unit.Default),
|
||||
Observable
|
||||
.FromEvent<PointerEventHandler, PointerRoutedEventArgs>(
|
||||
handler => (_, e) => handler(e),
|
||||
x => PointerPressed += x,
|
||||
x => PointerPressed -= x)
|
||||
.Where(args => args.GetCurrentPoint(this as UIElement).Properties.PointerUpdateKind == Windows.UI.Input.PointerUpdateKind.XButton1Pressed)
|
||||
handler => (_, e) => handler(e),
|
||||
x => PointerPressed += x,
|
||||
x => PointerPressed -= x)
|
||||
.Where(args =>
|
||||
args.GetCurrentPoint(this).Properties.PointerUpdateKind ==
|
||||
Windows.UI.Input.PointerUpdateKind.XButton1Pressed)
|
||||
.Do(args =>
|
||||
{
|
||||
if (mainFrame.CanGoBack)
|
||||
|
@ -184,49 +168,54 @@ namespace Sextant
|
|||
})
|
||||
.Select(_ => Unit.Default),
|
||||
Observable
|
||||
.FromEvent<RoutedEventHandler, RoutedEventArgs>(
|
||||
handler =>
|
||||
{
|
||||
void RoutedHandler(object sender, RoutedEventArgs e) => handler(e);
|
||||
return RoutedHandler;
|
||||
},
|
||||
x => backButton.Click += x,
|
||||
x => backButton.Click -= x)
|
||||
.Do(args =>
|
||||
.FromEvent<RoutedEventHandler, Unit>(
|
||||
handler =>
|
||||
{
|
||||
void RoutedHandler(object? sender, RoutedEventArgs e) => handler(Unit.Default);
|
||||
return RoutedHandler;
|
||||
},
|
||||
x => backButton.Click += x,
|
||||
x => backButton.Click -= x)
|
||||
.Do(_ =>
|
||||
{
|
||||
if (mainFrame.CanGoBack)
|
||||
{
|
||||
PopPage(true);
|
||||
}
|
||||
})
|
||||
.Select(_ => Unit.Default));
|
||||
}));
|
||||
|
||||
/// <inheritdoc />
|
||||
public IObservable<Unit> PopModal()
|
||||
{
|
||||
if (_contentDialog != null)
|
||||
if (_contentDialog is null)
|
||||
{
|
||||
_mirroredModalStack.TryPop(out _);
|
||||
_contentDialog.Hide();
|
||||
|
||||
if (_mirroredModalStack.TryPeek(out var modal))
|
||||
{
|
||||
if (modal == null)
|
||||
{
|
||||
return Observable.Return(Unit.Default).ObserveOn(_mainScheduler);
|
||||
}
|
||||
|
||||
_contentDialog = new ContentDialog();
|
||||
_contentDialog.FullSizeDesired = true;
|
||||
_contentDialog.IsPrimaryButtonEnabled = false;
|
||||
_contentDialog.IsSecondaryButtonEnabled = false;
|
||||
_contentDialog.Content = LocatePageFor(modal, null);
|
||||
|
||||
_ = _contentDialog.ShowAsync();
|
||||
}
|
||||
return Observable.Return(Unit.Default).ObserveOn(MainThreadScheduler);
|
||||
}
|
||||
|
||||
return Observable.Return(Unit.Default).ObserveOn(_mainScheduler);
|
||||
_mirroredModalStack.TryPop(out _);
|
||||
_contentDialog.Hide();
|
||||
|
||||
if (!_mirroredModalStack.TryPeek(out var modal))
|
||||
{
|
||||
return Observable.Return(Unit.Default).ObserveOn(MainThreadScheduler);
|
||||
}
|
||||
|
||||
if (modal is null)
|
||||
{
|
||||
return Observable.Return(Unit.Default).ObserveOn(MainThreadScheduler);
|
||||
}
|
||||
|
||||
_contentDialog = new ContentDialog
|
||||
{
|
||||
FullSizeDesired = true,
|
||||
IsPrimaryButtonEnabled = false,
|
||||
IsSecondaryButtonEnabled = false,
|
||||
Content = LocatePageFor(modal, null)
|
||||
};
|
||||
|
||||
_ = _contentDialog.ShowAsync();
|
||||
|
||||
return Observable.Return(Unit.Default).ObserveOn(MainThreadScheduler);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@ -244,18 +233,18 @@ namespace Sextant
|
|||
|
||||
_mirroredPageStack.Pop();
|
||||
|
||||
var view = mainFrame.Content as IViewFor;
|
||||
if (view == null)
|
||||
if (!(mainFrame.Content is IViewFor view))
|
||||
{
|
||||
_logger.Debug($"The view ({mainFrame.Content.GetType()}) does not implement IViewFor<>. Cannot get ViewModel.");
|
||||
return Observable.Return(Unit.Default).ObserveOn(_mainScheduler);
|
||||
var contentTypeName = mainFrame.Content?.GetType().ToString() ?? "Unknown Type";
|
||||
_logger.Debug($"The view ({contentTypeName}) does not implement IViewFor<>. Cannot get ViewModel.");
|
||||
return Observable.Return(Unit.Default).ObserveOn(MainThreadScheduler);
|
||||
}
|
||||
|
||||
_lastPoppedViewModel = view.ViewModel as IViewModel;
|
||||
|
||||
mainFrame.GoBack(animation);
|
||||
|
||||
return Observable.Return(Unit.Default).ObserveOn(_mainScheduler);
|
||||
return Observable.Return(Unit.Default).ObserveOn(MainThreadScheduler);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@ -281,29 +270,25 @@ namespace Sextant
|
|||
_mirroredPageStack.Pop();
|
||||
}
|
||||
|
||||
var view = mainFrame.Content as IViewFor;
|
||||
if (view == null)
|
||||
if (!(mainFrame.Content is IViewFor view))
|
||||
{
|
||||
_logger.Debug($"The view ({mainFrame.Content.GetType()}) does not implement IViewFor<>. Cannot get ViewModel.");
|
||||
return Observable.Return(Unit.Default).ObserveOn(_mainScheduler);
|
||||
var contentTypeName = mainFrame.Content?.GetType().ToString() ?? "Unknown Type";
|
||||
_logger.Debug($"The view ({contentTypeName}) does not implement IViewFor<>. Cannot get ViewModel.");
|
||||
return Observable.Return(Unit.Default).ObserveOn(MainThreadScheduler);
|
||||
}
|
||||
|
||||
_lastPoppedViewModel = view.ViewModel as IViewModel;
|
||||
|
||||
mainFrame.GoBack(animation);
|
||||
|
||||
return Observable.Return(Unit.Default).ObserveOn(_mainScheduler);
|
||||
return Observable.Return(Unit.Default).ObserveOn(MainThreadScheduler);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IObservable<Unit> PushModal(IViewModel modalViewModel, string? contract, bool withNavigationPage = true) =>
|
||||
Observable
|
||||
.Start(
|
||||
() =>
|
||||
{
|
||||
// ignore withNavigationPage, not necessary for UWP.
|
||||
return LocatePageFor(modalViewModel, contract);
|
||||
},
|
||||
() => LocatePageFor(modalViewModel, contract), // ignore withNavigationPage, not necessary for UWP.
|
||||
CurrentThreadScheduler.Instance)
|
||||
.ObserveOn(CurrentThreadScheduler.Instance)
|
||||
.SelectMany(
|
||||
|
@ -311,16 +296,18 @@ namespace Sextant
|
|||
{
|
||||
_mirroredModalStack.Push(modalViewModel);
|
||||
|
||||
if (_contentDialog != null && ModalVisible)
|
||||
if (_contentDialog is not null && ModalVisible)
|
||||
{
|
||||
_contentDialog.Hide();
|
||||
}
|
||||
|
||||
_contentDialog = new ContentDialog();
|
||||
_contentDialog.FullSizeDesired = true;
|
||||
_contentDialog.IsPrimaryButtonEnabled = false;
|
||||
_contentDialog.IsSecondaryButtonEnabled = false;
|
||||
_contentDialog.Content = page;
|
||||
_contentDialog = new ContentDialog
|
||||
{
|
||||
FullSizeDesired = true,
|
||||
IsPrimaryButtonEnabled = false,
|
||||
IsSecondaryButtonEnabled = false,
|
||||
Content = page
|
||||
};
|
||||
|
||||
_ = _contentDialog.ShowAsync();
|
||||
|
||||
|
@ -335,11 +322,7 @@ namespace Sextant
|
|||
bool animate) =>
|
||||
Observable
|
||||
.Start(
|
||||
() =>
|
||||
{
|
||||
// ignore withNavigationPage, not necessary for UWP.
|
||||
return LocatePageTypeFor(viewModel, contract);
|
||||
},
|
||||
() => LocatePageTypeFor(viewModel, contract), // ignore withNavigationPage, not necessary for UWP.
|
||||
CurrentThreadScheduler.Instance)
|
||||
.ObserveOn(CurrentThreadScheduler.Instance)
|
||||
.SelectMany(
|
||||
|
@ -351,13 +334,14 @@ namespace Sextant
|
|||
_mirroredPageStack.Push(viewModel);
|
||||
|
||||
mainFrame.Navigate(pageType, null, new SuppressNavigationTransitionInfo());
|
||||
if (mainFrame.Content is IViewFor)
|
||||
if (mainFrame.Content is IViewFor viewForReset)
|
||||
{
|
||||
((IViewFor)mainFrame.Content).ViewModel = viewModel;
|
||||
viewForReset.ViewModel = viewModel;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug($"The view ({mainFrame.Content.GetType()}) does not implement IViewFor<>. Cannot set ViewModel of type, {viewModel.GetType()}, on view.");
|
||||
var contentTypeName = mainFrame.Content?.GetType().ToString() ?? "Unknown Type";
|
||||
_logger.Debug($"The view ({contentTypeName}) does not implement IViewFor<>. Cannot set ViewModel of type, {viewModel.GetType()}, on view.");
|
||||
}
|
||||
|
||||
mainFrame.BackStack.Clear();
|
||||
|
@ -378,41 +362,26 @@ namespace Sextant
|
|||
_mirroredPageStack.Push(viewModel);
|
||||
|
||||
mainFrame.Navigate(pageType, null, animation);
|
||||
if (mainFrame.Content is IViewFor)
|
||||
if (mainFrame.Content is IViewFor viewFor)
|
||||
{
|
||||
((IViewFor)mainFrame.Content).ViewModel = viewModel;
|
||||
viewFor.ViewModel = viewModel;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug($"The view ({mainFrame.Content.GetType()}) does not implement IViewFor<>. Cannot set ViewModel of type, {viewModel.GetType()}, on view.");
|
||||
var contentTypeName = mainFrame.Content?.GetType().ToString() ?? "Unknown Type";
|
||||
_logger.Debug($"The view ({contentTypeName}) does not implement IViewFor<>. Cannot set ViewModel of type, {viewModel.GetType()}, on view.");
|
||||
}
|
||||
|
||||
return Observable.Return(Unit.Default);
|
||||
});
|
||||
|
||||
private IViewModel? CurrentViewModel() => (IViewModel?)(mainFrame.Content as IViewFor)?.ViewModel;
|
||||
|
||||
private IView LocateNavigationFor(IViewModel viewModel)
|
||||
{
|
||||
var view = _viewLocator.ResolveView(viewModel, "NavigationView");
|
||||
var navigationPage = view as IView;
|
||||
|
||||
if (navigationPage is null)
|
||||
{
|
||||
_logger.Debug($"No navigation view could be located for type '{viewModel.GetType().FullName}', using the default navigation page.");
|
||||
navigationPage = Locator.Current.GetService<IView>(nameof(NavigationView)) ?? Locator.Current.GetService<IView>();
|
||||
}
|
||||
|
||||
return navigationPage;
|
||||
}
|
||||
|
||||
private Type LocatePageTypeFor(object viewModel, string? contract)
|
||||
private static Type LocatePageTypeFor(object viewModel, string? contract)
|
||||
{
|
||||
var uwpViewTypeResolver = Locator.Current.GetService<ViewTypeResolver>(contract);
|
||||
|
||||
var viewType = uwpViewTypeResolver.ResolveViewType(viewModel.GetType());
|
||||
|
||||
if (viewType == null)
|
||||
if (viewType is null)
|
||||
{
|
||||
throw new InvalidOperationException($"No view could be located for type '{viewModel.GetType().FullName}', contract '{contract}'. Be sure Splat has an appropriate registration.");
|
||||
}
|
||||
|
@ -425,17 +394,17 @@ namespace Sextant
|
|||
var view = _viewLocator.ResolveView(viewModel, contract);
|
||||
var page = view as Page;
|
||||
|
||||
if (view == null)
|
||||
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 == null)
|
||||
if (view is null)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot find view for '{viewModel.GetType().FullName}', contract '{contract}' does not implement IViewFor.");
|
||||
}
|
||||
|
||||
if (page == null)
|
||||
if (page is null)
|
||||
{
|
||||
throw new InvalidOperationException($"Resolved view '{view.GetType().FullName}' for type '{viewModel.GetType().FullName}', contract '{contract}' is not a Page.");
|
||||
}
|
||||
|
|
|
@ -30,8 +30,8 @@ namespace Sextant
|
|||
private readonly IScheduler _backgroundScheduler;
|
||||
private readonly IScheduler _mainScheduler;
|
||||
private readonly IViewLocator _viewLocator;
|
||||
private readonly Stack<UIViewController> _navigationPages = new Stack<UIViewController>();
|
||||
private readonly Subject<IViewModel?> _pagePopped = new Subject<IViewModel?>();
|
||||
private readonly Stack<UIViewController> _navigationPages = new();
|
||||
private readonly Subject<IViewModel?> _pagePopped = new();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NavigationViewController" /> class.
|
||||
|
@ -110,9 +110,8 @@ namespace Sextant
|
|||
IViewModel viewModel,
|
||||
string? contract,
|
||||
bool resetStack,
|
||||
bool animate = true)
|
||||
{
|
||||
return Observable.Start(
|
||||
bool animate = true) =>
|
||||
Observable.Start(
|
||||
() =>
|
||||
{
|
||||
var page = LocatePageFor(viewModel, contract);
|
||||
|
@ -150,7 +149,6 @@ namespace Sextant
|
|||
return Disposable.Empty;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override UIViewController PopViewController(bool animated)
|
||||
|
@ -168,13 +166,13 @@ namespace Sextant
|
|||
var viewFor = _viewLocator.ResolveView(viewModel, contract);
|
||||
var page = viewFor as UIViewController;
|
||||
|
||||
if (viewFor == null)
|
||||
if (viewFor 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 (page == null)
|
||||
if (page is null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Resolved view '{viewFor.GetType().FullName}' for type '{viewModel.GetType().FullName}', contract '{contract}' is not a Page.");
|
||||
|
@ -185,9 +183,6 @@ namespace Sextant
|
|||
return page;
|
||||
}
|
||||
|
||||
private void SetPageTitle(UIViewController page, string resourceKey)
|
||||
{
|
||||
page.Title = resourceKey;
|
||||
}
|
||||
private void SetPageTitle(UIViewController page, string resourceKey) => page.Title = resourceKey;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,20 +14,18 @@ namespace Sextant
|
|||
/// </summary>
|
||||
public class Sextant
|
||||
{
|
||||
private static readonly Lazy<Sextant> _sextant = new Lazy<Sextant>();
|
||||
private static readonly Lazy<Sextant> _sextant = new();
|
||||
|
||||
static Sextant()
|
||||
{
|
||||
static Sextant() =>
|
||||
Locator.RegisterResolverCallbackChanged(() =>
|
||||
{
|
||||
if (Locator.CurrentMutable == null)
|
||||
if (Locator.CurrentMutable is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Instance.Initialize();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instance of <see cref="Sextant"/>.
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
<Project Sdk="MSBuild.Sdk.Extras">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;Xamarin.iOS10</TargetFrameworks>
|
||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net461;uap10.0.16299</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.0;Xamarin.iOS10;Xamarin.TVOS10;net5.0</TargetFrameworks>
|
||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net461;net472;uap10.0.16299</TargetFrameworks>
|
||||
<AssemblyName>Sextant</AssemblyName>
|
||||
<RootNamespace>Sextant</RootNamespace>
|
||||
<PackageId>Sextant</PackageId>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<WarningsAsErrors>CS8625;CS8604;CS8600;CS8614;CS8603;CS8618;CS8619</WarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Platforms\**\*.cs" />
|
||||
<None Include="Platforms\**\*.cs" />
|
||||
<PackageReference Include="System.Collections.Immutable" Version="5.0.0" />
|
||||
<PackageReference Include="ReactiveUI" Version="12.*" />
|
||||
<PackageReference Include="ReactiveUI" Version="13.*" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" $(TargetFramework.StartsWith('Xamarin.iOS')) ">
|
||||
|
@ -24,8 +23,29 @@
|
|||
<Reference Include="System.Runtime.Serialization" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" $(TargetFramework.StartsWith('net461')) ">
|
||||
<Compile Include="Platforms\net461\**\*.cs" />
|
||||
<ItemGroup Condition=" $(TargetFramework.StartsWith('Xamarin.WatchOS')) ">
|
||||
<Compile Include="Platforms\apple-common\**\*.cs" />
|
||||
<Compile Include="Platforms\ios\**\*.cs" />
|
||||
<Compile Include="Platforms\uikit-common\**\*.cs" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" $(TargetFramework.StartsWith('Xamarin.TVOS')) ">
|
||||
<Compile Include="Platforms\apple-common\**\*.cs" />
|
||||
<Compile Include="Platforms\ios\**\*.cs" />
|
||||
<Compile Include="Platforms\uikit-common\**\*.cs" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" $(TargetFramework.StartsWith('Xamarin.Mac')) ">
|
||||
<Compile Include="Platforms\apple-common\**\*.cs" />
|
||||
<Compile Include="Platforms\ios\**\*.cs" />
|
||||
<Compile Include="Platforms\uikit-common\**\*.cs" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" $(TargetFramework.StartsWith('net4')) ">
|
||||
<Compile Include="Platforms\net4\**\*.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" $(TargetFramework.StartsWith('uap')) ">
|
||||
|
@ -37,4 +57,8 @@
|
|||
<Compile Include="Platforms\netstandard2.0\**\*.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<ItemGroup Condition=" $(TargetFramework.StartsWith('net5')) ">
|
||||
<Compile Include="Platforms\net5\**\*.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=abstractions/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=navigation/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=platforms/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=platforms_005Cnet4/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=platforms_005Cnet5/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=platforms_005Cnetstandard2_002E0/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=platforms_005Cuap/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=platforms_005Cuap_005Cmixins/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=platforms_005Cuikit_002Dcommon/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=system/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=system_005Creactive/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=system_005Creactive_005Clinq/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
|
@ -28,9 +28,8 @@ namespace System.Reactive.Linq
|
|||
this IObservable<T> observable,
|
||||
[CallerMemberName]string? callerMemberName = null,
|
||||
[CallerFilePath]string? callerFilePath = null,
|
||||
[CallerLineNumber]int callerLineNumber = 0)
|
||||
{
|
||||
return observable
|
||||
[CallerLineNumber]int callerLineNumber = 0) =>
|
||||
observable
|
||||
.Subscribe(
|
||||
_ => { },
|
||||
ex =>
|
||||
|
@ -40,6 +39,5 @@ namespace System.Reactive.Linq
|
|||
|
||||
Debugger.Break();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace System.Reactive.Linq
|
|||
[Obsolete("This extension method causes conflicts in the System.Reactive.Linq namespace")]
|
||||
public static IObservable<Unit> ToSignal<T>(this IObservable<T> observable)
|
||||
{
|
||||
if (observable == null)
|
||||
if (observable is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(observable));
|
||||
}
|
||||
|
|
|
@ -17,9 +17,6 @@ namespace System.Reactive.Linq
|
|||
/// <param name="observable">The observable to add the condition to.</param>
|
||||
/// <returns>An observable which will not signal unless the value is not null.</returns>
|
||||
[Obsolete("This extension method causes conflicts in the System.Reactive.Linq namespace")]
|
||||
public static IObservable<T> WhereNotNull<T>(this IObservable<T> observable)
|
||||
{
|
||||
return observable.Where(x => x != null);
|
||||
}
|
||||
public static IObservable<T> WhereNotNull<T>(this IObservable<T?> observable) => observable.Where(x => x is not null).Select(x => x!);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace Sextant
|
|||
get
|
||||
{
|
||||
var locator = Locator.Current.GetService<IViewModelFactory>();
|
||||
if (locator == null)
|
||||
if (locator is null)
|
||||
{
|
||||
throw new ViewModelFactoryNotFoundException("Could not find a default ViewModelFactory. This should never happen, your dependency resolver is broken");
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче