reactiveui / Sextant

A ReactiveUI navigation library for Xamarin.Forms
MIT License
157 stars 26 forks source link

[Bug]: Push FlyoutPage resetStack: true does not set the root page as flyout on Android. #808

Open DanielCauser opened 2 months ago

DanielCauser commented 2 months ago

Describe the bug 🐞

I'm using sextant to create a simple Login Page -> Logedin Page app.

FIrst a simple root Navigation page where the app first navigates to. After, the user clicks on Login Button and the app navigates to a classic FlyoutPage.

The issue I see is specific on Android. When I navigate to the Flyout page, it just acts as if its a Navigation Page.

Step to reproduce

  1. App.cs navigate https://github.com/DanielCauser/SextantNavigation/blob/main/SextantNavigation/App.xaml.cs#L21
  2. On the MainPage of the app, user clicks on the Login Button. https://github.com/DanielCauser/SextantNavigation/blob/main/SextantNavigation/MainViewModel.cs#L17
  3. Notice that on Android, when the app finishes navigating there is no hamburger menu (Flyout) Present.

Reproduction repository

https://github.com/DanielCauser/SextantNavigation

Expected behavior

When you clean the stack, and navigate to Flyout Page, the flyout popover behaviour should work.

Screenshots 🖼️

User lands on pretty Login page. Screenshot 2024-09-03 at 8 33 06 PM

Once user Logs in, they navigate to the flyoutpage (For the life of me I can't make the hamburger button show, but the flyout page behaviour is there): Screenshot 2024-09-03 at 8 19 30 PM

However on Android, the apps just navigates to the Flyout -> Detail page and gets stuck there. No Flyout popoover behaviour happens. Screenshot 2024-09-03 at 8 41 24 PM

IDE

Visual Studio 2022

Operating system

Mac

Version

3.0.1

Device

Any Android Device

ReactiveUI Version

ReactiveUI.Maui" Version="20.1.1"

Additional information ℹ️

No response

DanielCauser commented 2 months ago

Also a link to the Slack question I left a while ago :(

https://reactivex.slack.com/archives/C02AJB872/p1725410970584099

Slack
DanielCauser commented 2 months ago

UPDATE:

I've been poking around with the Main page and NavigationView.

It seems that when I Navigate to the Root Flyout page, Sextant is converting it to its own NavigationView.

I did this:

Locator.Current.GetService<IViewStackService>().PushPage<LogedInViewModel>(resetStack: true);
var vm = Locator.Current.GetService<LogedInViewModel>();
var page = locatorView.ResolveView(vm);
page.ViewModel = vm;
MainPage = (LogedInPage) page;

The app does navigate to the FlyoutPage on Android. HOWEVER, this is messing something up on the stack, because I start getting all sorts of random exceptions(When I switch back to the MainViewModel as the root).

:(

DanielCauser commented 2 months ago

UPDATE 2

After doing the above to navigate the to Root Flyout I try to "Logout", by Navigating to the MainViewModel again:

Locator.Current.GetService<IViewStackService>().PushPage<SplashViewModel>(resetStack: true);
MainPage = Locator.Current.GetNavigationView("NavigationView");

But then I get this exception. Not sure what to do next here :(

[mono-rt] [ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidOperationException: Pending Navigations still processing
[mono-rt]    at Microsoft.Maui.Controls.NavigationPage.SendHandlerUpdateAsync(Boolean animated, Action processStackChanges, Action firePostNavigatingEvents, Action fireNavigatedEvents) in /_/src/Controls/src/Core/NavigationPage/NavigationPage.cs:line 650
[mono-rt]    at System.Reactive.PlatformServices.ExceptionServicesImpl.Rethrow(Exception exception)
[mono-rt]    at System.Reactive.ExceptionHelpers.Throw(Exception exception)
[mono-rt]    at System.Reactive.Stubs.<>c.<.cctor>b__2_1(Exception ex)
[mono-rt]    at System.Reactive.AnonymousSafeObserver`1[[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]].OnError(Exception error)
[mono-rt]    at System.Reactive.Sink`1[[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]].ForwardOnError(Exception error)
[mono-rt]    at System.Reactive.Sink`2[[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263],[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]].OnError(Exception error)
[mono-rt]    at System.Reactive.Sink`1[[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]].ForwardOnError(Exception error)
[mono-rt]    at System.Reactive.Linq.ObservableImpl.SelectMany`2.ObservableSelector._.InnerObserver[[Microsoft.Maui.Controls.Page, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]].OnError(Exception error)
[mono-rt]    at System.Reactive.Sink`1[[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]].ForwardOnError(Exception error)
[mono-rt]    at System.Reactive.Linq.ObservableImpl.Throw`1._.<>c[[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]].<Run>b__2_0(_ this)
[mono-rt]    at System.Reactive.Concurrency.Scheduler.<>c__75`1[[System.Reactive.Linq.ObservableImpl.Throw`1._[[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]], System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]].<ScheduleAction>b__75_0(IScheduler _, ValueTuple`2 tuple)
[mono-rt]    at System.Reactive.Concurrency.ImmediateScheduler.Schedule[ValueTuple`2](ValueTuple`2 state, Func`3 action)
[mono-rt]    at System.Reactive.Concurrency.Scheduler.ScheduleAction[_](IScheduler scheduler, _ state, Action`1 action)
[mono-rt]    at System.Reactive.Linq.ObservableImpl.Throw`1._[[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]].Run(IScheduler scheduler)
[mono-rt]    at System.Reactive.Linq.ObservableImpl.Throw`1[[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]].Run(_ sink)
[mono-rt]    at System.Reactive.Producer`2[[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263],[System.Reactive.Linq.ObservableImpl.Throw`1._[[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]], System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]].SubscribeRaw(IObserver`1 observer, Boolean enableSafeguard)
[mono-rt]    at System.ObservableExtensions.SubscribeSafe[Unit](IObservable`1 source, IObserver`1 observer)
[mono-rt]    at System.Reactive.Linq.ObservableImpl.SelectMany`2.ObservableSelector._[[Microsoft.Maui.Controls.Page, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]].SubscribeInner(IObservable`1 inner)
[mono-rt]    at System.Reactive.Linq.ObservableImpl.SelectMany`2.ObservableSelector._[[Microsoft.Maui.Controls.Page, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]].OnNext(Page value)
[mono-rt]    at System.Reactive.Sink`1[[Microsoft.Maui.Controls.Page, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].ForwardOnNext(Page value)
[mono-rt]    at System.Reactive.ObserveOnObserverNew`1[[Microsoft.Maui.Controls.Page, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].DrainStep(ConcurrentQueue`1 q)
[mono-rt]    at System.Reactive.ObserveOnObserverNew`1[[Microsoft.Maui.Controls.Page, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].DrainShortRunning(IScheduler recursiveScheduler)
[mono-rt]    at System.Reactive.ObserveOnObserverNew`1.<>c[[Microsoft.Maui.Controls.Page, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].<.cctor>b__17_0(IScheduler scheduler, ObserveOnObserverNew`1 self)
[mono-rt]    at System.Reactive.Concurrency.ScheduledItem`2[[System.TimeSpan, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Reactive.ObserveOnObserverNew`1[[Microsoft.Maui.Controls.Page, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]].InvokeCore()
[mono-rt]    at System.Reactive.Concurrency.ScheduledItem`1[[System.TimeSpan, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Invoke()
[mono-rt]    at System.Reactive.Concurrency.CurrentThreadScheduler.Trampoline.Run(SchedulerQueue`1 queue)
[mono-rt]    at System.Reactive.Concurrency.CurrentThreadScheduler.Schedule[ValueTuple`2](ValueTuple`2 state, TimeSpan dueTime, Func`3 action)
[mono-rt]    at System.Reactive.Concurrency.LocalScheduler.Schedule[ValueTuple`2](ValueTuple`2 state, Func`3 action)
[mono-rt]    at System.Reactive.Concurrency.Scheduler.ScheduleAction[ValueTuple`2](IScheduler scheduler, ValueTuple`2 state, Action`1 action)
[mono-rt]    at System.Reactive.Producer`2[[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263],[System.Reactive.Linq.ObservableImpl.Do`1.OnNext._[[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]], System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]].SubscribeRaw(IObserver`1 observer, Boolean enableSafeguard)
[mono-rt]    at System.Reactive.Producer`2[[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263],[System.Reactive.Linq.ObservableImpl.Do`1.OnNext._[[System.Reactive.Unit, System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]], System.Reactive, Version=6.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263]].Subscribe(IObserver`1 observer)
[mono-rt]    at System.ObservableExtensions.Subscribe[Unit](IObservable`1 source)
[mono-rt]    at ICTarget.Application.ViewModels.SplashViewModel.<>c__DisplayClass1_0.<<safeActivated>b__2>d.MoveNext() in /Users/danielcauser/Downloads/icbolt/src/ICTarget.Application/ViewModels/SplashViewModel.cs:line 35
[mono-rt] --- End of stack trace from previous location ---
[mono-rt]    at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_0(Object state)
[mono-rt]    at Android.App.SyncContext.<>c__DisplayClass2_0.<Post>b__0() in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.App/SyncContext.cs:line 36
[mono-rt]    at Java.Lang.Thread.RunnableImplementor.Run() in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Java.Lang/Thread.cs:line 36
[mono-rt]    at Java.Lang.IRunnableInvoker.n_Run(IntPtr jnienv, IntPtr native__this) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net8.0/android-34/mcw/Java.Lang.IRunnable.cs:line 84
[mono-rt]    at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V(_JniMarshal_PP_V callback, IntPtr jnienv, IntPtr klazz) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:line 26
[libc] FORTIFY: pthread_mutex_lock called on a destroyed mutex (0x6e2ba78028)
DanielCauser commented 2 months ago

I went to check if a Plain Maui sample would work. It does not have dependencies on sextant or reactiveUI.

This is where navigation happens: https://github.com/DanielCauser/SextantNavigation/blob/maui-test/SextantNavigation/App.xaml.cs#L20

Also the MainPage is a straight up FlyoutPage, no ReactivePage. https://github.com/DanielCauser/SextantNavigation/blob/maui-test/SextantNavigation/MainPage.xaml.cs#L8

And the Loged in Page is just a ContentPage https://github.com/DanielCauser/SextantNavigation/blob/maui-test/SextantNavigation/LoginPage.xaml.cs#L5

With plain Maui components, the navigation works as expected on iOS and Android =/

Screenshot 2024-09-04 at 4 21 15 PM Screenshot 2024-09-04 at 4 21 20 PM Screenshot 2024-09-04 at 4 21 26 PM

GitHub
SextantNavigation/SextantNavigation/App.xaml.cs at maui-test · DanielCauser/SextantNavigation
Contribute to DanielCauser/SextantNavigation development by creating an account on GitHub.
GitHub
SextantNavigation/SextantNavigation/MainPage.xaml.cs at maui-test · DanielCauser/SextantNavigation
Contribute to DanielCauser/SextantNavigation development by creating an account on GitHub.
GitHub
SextantNavigation/SextantNavigation/LoginPage.xaml.cs at maui-test · DanielCauser/SextantNavigation
Contribute to DanielCauser/SextantNavigation development by creating an account on GitHub.
glennawatson commented 2 months ago

I think Chris put up his hand to help with this one.

The indepth analysis definitely helps

ChrisPulman commented 2 months ago

Hi I have taken a look and can see your issues, I will have to carry on looking at this over the next few days, I will try to find a resolution to the issues.

DanielCauser commented 2 months ago

Thank you everyone. I will also keep poking around to see if I can bring more info here.

DanielCauser commented 1 month ago

Hi @ChrisPulman, were you able to have a look at the issue? Let me know if there is anything I can do to help.

DanielCauser commented 1 month ago

Hello folk. I'm back to check if there are any news on this bug. Please let me know if there is anything I can to to help.

DanielCauser commented 3 weeks ago

Hey Y'all. Just coming back to tell you that I opened a ticket with don't MAUI.

I dove deeper in the Sextant code just to find out that the problem seems to be here:

https://github.com/reactiveui/Sextant/blob/e221e445ab91d92739f69e7e63996bd19894d882/src/Sextant.Maui/NavigationView.cs#L184

I also found the same exact issue from a different person, and the ticket has been open for over a year. https://github.com/dotnet/maui/issues/18228

I don't think the MAUI folk will go anywhere with it. So either we'll need to figure out a way to change the root of the app and trash/recycle the NavigationPage somehow.