From 40fa4f2ebdafd02702b6985bbf0d02fc1ac9f8a2 Mon Sep 17 00:00:00 2001
From: rlittlesii <6969701+RLittlesII@users.noreply.github.com>
Date: Sun, 26 Jan 2020 02:36:25 -0600
Subject: [PATCH 1/3] fix: NavigateBack losing values on the NavigationStack
---
src/ReactiveUI.XamForms/RoutedViewHost.cs | 91 +++++++++++++----------
1 file changed, 53 insertions(+), 38 deletions(-)
diff --git a/src/ReactiveUI.XamForms/RoutedViewHost.cs b/src/ReactiveUI.XamForms/RoutedViewHost.cs
index 1d6c114352..7c01588da6 100644
--- a/src/ReactiveUI.XamForms/RoutedViewHost.cs
+++ b/src/ReactiveUI.XamForms/RoutedViewHost.cs
@@ -6,13 +6,13 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reactive;
+using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
using System.Reflection;
using Splat;
using Xamarin.Forms;
-#pragma warning disable RCS1090 // Call 'ConfigureAwait(false)'.
namespace ReactiveUI.XamForms
{
///
@@ -20,7 +20,8 @@ namespace ReactiveUI.XamForms
///
///
///
- public class RoutedViewHost : NavigationPage, IActivatableView
+ [SuppressMessage("Readability", "RCS1090: Call 'ConfigureAwait(false)", Justification = "This class interacts with the UI thread.")]
+ public class RoutedViewHost : NavigationPage, IActivatableView, IEnableLogger
{
///
/// The router bindable property.
@@ -38,13 +39,13 @@ public class RoutedViewHost : NavigationPage, IActivatableView
/// You *must* register an IScreen class representing your App's main Screen.
public RoutedViewHost()
{
- this.WhenActivated(new Action>(d =>
+ this.WhenActivated(disposable =>
{
bool currentlyPopping = false;
bool popToRootPending = false;
bool userInstigated = false;
- d(this.WhenAnyObservable(x => x.Router.NavigationChanged)
+ this.WhenAnyObservable(x => x.Router.NavigationChanged)
.Where(_ => Router.NavigationStack.Count == 0)
.Select(x =>
{
@@ -54,18 +55,22 @@ public RoutedViewHost()
popToRootPending = true;
return x;
})
- .Subscribe());
-
- var previousCount =
- this.WhenAnyObservable(x => x.Router.NavigationChanged)
- .CountChanged()
- .ObserveOn(Router.Scheduler)
- .Select(_ => Router.NavigationStack.Count)
- .StartWith(Router.NavigationStack.Count);
-
- var currentCount = previousCount.Skip(1);
+ .Subscribe()
+ .DisposeWith(disposable);
+
+ Router.NavigationChanged
+ .CountChanged()
+ .Select(_ => Router.NavigationStack.Count)
+ .StartWith(Router.NavigationStack.Count)
+ .Buffer(2, 1)
+ .Select(counts => new
+ {
+ Delta = counts[0] - counts[1],
+ Current = counts[1],
- d(Observable.Zip(previousCount, currentCount, (previous, current) => new { Delta = previous - current, Current = current })
+ // cache current viewmodel as it might change if some other Navigation command is executed midway
+ CurrentViewModel = Router.GetCurrentViewModel()
+ })
.Where(_ => !userInstigated)
.Where(x => x.Delta > 0)
.SelectMany(
@@ -94,14 +99,19 @@ public RoutedViewHost()
finally
{
currentlyPopping = false;
- ((IViewFor)CurrentPage).ViewModel = Router.GetCurrentViewModel();
+ if (CurrentPage is IViewFor page && x.CurrentViewModel != null)
+ {
+ page.ViewModel = x.CurrentViewModel;
+ }
}
return Unit.Default;
})
- .Subscribe());
+ .Subscribe()
+ .DisposeWith(disposable);
- d(this.WhenAnyObservable(x => x.Router.Navigate)
+ Router
+ .Navigate
.SelectMany(_ => PageForViewModel(Router.GetCurrentViewModel()))
.SelectMany(async page =>
{
@@ -125,20 +135,21 @@ public RoutedViewHost()
popToRootPending = false;
return page;
})
- .Subscribe());
+ .Subscribe()
+ .DisposeWith(disposable);
var poppingEvent = Observable.FromEvent, Unit>(
- eventHandler =>
- {
- void Handler(object sender, NavigationEventArgs e) => eventHandler(Unit.Default);
- return Handler;
- },
- x => Popped += x,
- x => Popped -= x);
+ eventHandler =>
+ {
+ void Handler(object sender, NavigationEventArgs e) => eventHandler(Unit.Default);
+ return Handler;
+ },
+ x => Popped += x,
+ x => Popped -= x);
// NB: Catch when the user hit back as opposed to the application
// requesting Back via NavigateBack
- d(poppingEvent
+ poppingEvent
.Where(_ => !currentlyPopping && Router != null)
.Subscribe(_ =>
{
@@ -146,19 +157,23 @@ public RoutedViewHost()
try
{
- if (Router.NavigationStack.Count > 1)
- {
- Router.NavigationStack.RemoveAt(Router.NavigationStack.Count - 1);
- }
+ Router.NavigationStack.RemoveAt(Router.NavigationStack.Count - 1);
}
finally
{
userInstigated = false;
}
- ((IViewFor)CurrentPage).ViewModel = Router.GetCurrentViewModel();
- }));
- }));
+ var vm = Router.GetCurrentViewModel();
+ if (CurrentPage is IViewFor page && vm != null)
+ {
+ // don't replace view model if vm is null
+ page.ViewModel = vm;
+ }
+ })
+ .DisposeWith(disposable);
+ });
+
var screen = Locator.Current.GetService();
if (screen == null)
{
@@ -169,8 +184,8 @@ public RoutedViewHost()
this.WhenAnyValue(x => x.Router)
.SelectMany(router =>
- router
- .NavigationStack
+ {
+ return router.NavigationStack
.ToObservable()
.Select(x => (Page)ViewLocator.Current.ResolveView(x))
.SelectMany(x => PushAsync(x).ToObservable())
@@ -184,7 +199,8 @@ public RoutedViewHost()
((IViewFor)CurrentPage).ViewModel = vm;
CurrentPage.Title = vm.UrlPathSegment;
- }))
+ });
+ })
.Subscribe();
}
@@ -227,4 +243,3 @@ protected IObservable PageForViewModel(IRoutableViewModel vm)
}
}
}
-#pragma warning restore RCS1090 // Call 'ConfigureAwait(false)'.
From da03218c3776a3607270b41389270d0ce8553214 Mon Sep 17 00:00:00 2001
From: rlittlesii <6969701+RLittlesII@users.noreply.github.com>
Date: Sun, 26 Jan 2020 14:47:26 -0600
Subject: [PATCH 2/3] Added Concat()
---
src/ReactiveUI.XamForms/RoutedViewHost.cs | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/ReactiveUI.XamForms/RoutedViewHost.cs b/src/ReactiveUI.XamForms/RoutedViewHost.cs
index 7c01588da6..160e6135f3 100644
--- a/src/ReactiveUI.XamForms/RoutedViewHost.cs
+++ b/src/ReactiveUI.XamForms/RoutedViewHost.cs
@@ -135,6 +135,7 @@ public RoutedViewHost()
popToRootPending = false;
return page;
})
+ .Concat()
.Subscribe()
.DisposeWith(disposable);
From 877ddce4530d23f55992f36c7cb07b382160cdba Mon Sep 17 00:00:00 2001
From: rlittlesii <6969701+RLittlesII@users.noreply.github.com>
Date: Sun, 26 Jan 2020 14:50:39 -0600
Subject: [PATCH 3/3] fix Concat()
---
src/ReactiveUI.XamForms/RoutedViewHost.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/ReactiveUI.XamForms/RoutedViewHost.cs b/src/ReactiveUI.XamForms/RoutedViewHost.cs
index 160e6135f3..dfe370c53b 100644
--- a/src/ReactiveUI.XamForms/RoutedViewHost.cs
+++ b/src/ReactiveUI.XamForms/RoutedViewHost.cs
@@ -73,7 +73,7 @@ public RoutedViewHost()
})
.Where(_ => !userInstigated)
.Where(x => x.Delta > 0)
- .SelectMany(
+ .Select(
async x =>
{
// XF doesn't provide a means of navigating back more than one screen at a time apart from navigating right back to the root page
@@ -107,6 +107,7 @@ public RoutedViewHost()
return Unit.Default;
})
+ .Concat()
.Subscribe()
.DisposeWith(disposable);
@@ -135,7 +136,6 @@ public RoutedViewHost()
popToRootPending = false;
return page;
})
- .Concat()
.Subscribe()
.DisposeWith(disposable);