From 69aa6fc04424ee67ece170175c4ccf716200ceb6 Mon Sep 17 00:00:00 2001 From: Dinis Vieira Date: Thu, 9 Nov 2023 15:09:37 +0000 Subject: [PATCH] PM-3349 PM-3350 Started using OnNavigatedTo/From instead of On(Dis)Appearing for LoginPage and LoginSSOPage to avoid the "Modal loading" issues in iOS Also had to add IsInitialized logic to these pages because OnNavigatedTo can be called twice in some scenario. Some minor migrations of Device to DeviceInfo was also done --- src/Core/Pages/Accounts/LoginPage.xaml.cs | 49 +++++++++---------- src/Core/Pages/Accounts/LoginPageViewModel.cs | 2 - src/Core/Pages/Accounts/LoginSsoPage.xaml.cs | 40 +++++++++------ src/Core/Pages/BaseContentPage.cs | 7 ++- 4 files changed, 54 insertions(+), 44 deletions(-) diff --git a/src/Core/Pages/Accounts/LoginPage.xaml.cs b/src/Core/Pages/Accounts/LoginPage.xaml.cs index 4146bf04b..1f8c6ff67 100644 --- a/src/Core/Pages/Accounts/LoginPage.xaml.cs +++ b/src/Core/Pages/Accounts/LoginPage.xaml.cs @@ -1,16 +1,10 @@ -using System; -using System.Threading.Tasks; -using Bit.App.Models; +using Bit.App.Models; using Bit.App.Utilities; using Bit.Core; using Bit.Core.Abstractions; using Bit.Core.Enums; -using Bit.Core.Services; using Bit.Core.Utilities; -using Microsoft.Maui.Controls; -using Microsoft.Maui; - namespace Bit.App.Pages { public partial class LoginPage : BaseContentPage @@ -30,11 +24,11 @@ namespace Bit.App.Pages _broadcasterService = ServiceContainer.Resolve(); _vm = BindingContext as LoginPageViewModel; _vm.Page = this; - _vm.StartTwoFactorAction = () => Device.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync()); - _vm.LogInSuccessAction = () => Device.BeginInvokeOnMainThread(async () => await LogInSuccessAsync()); + _vm.StartTwoFactorAction = () => MainThread.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync()); + _vm.LogInSuccessAction = () => MainThread.BeginInvokeOnMainThread(async () => await LogInSuccessAsync()); _vm.LogInWithDeviceAction = () => StartLoginWithDeviceAsync().FireAndForget(); - _vm.StartSsoLoginAction = () => Device.BeginInvokeOnMainThread(async () => await StartSsoLoginAsync()); - _vm.UpdateTempPasswordAction = () => Device.BeginInvokeOnMainThread(async () => await UpdateTempPasswordAsync()); + _vm.StartSsoLoginAction = () => MainThread.BeginInvokeOnMainThread(async () => await StartSsoLoginAsync()); + _vm.UpdateTempPasswordAction = () => MainThread.BeginInvokeOnMainThread(async () => await UpdateTempPasswordAsync()); _vm.CloseAction = async () => { await _accountListOverlay.HideAsync(); @@ -50,8 +44,7 @@ namespace Bit.App.Pages _vm.Email = email; MasterPasswordEntry = _masterPassword; - // TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes - if (Device.RuntimePlatform == Device.iOS) + if (DeviceInfo.Platform == DevicePlatform.iOS) { ToolbarItems.Add(_moreItem); } @@ -73,14 +66,19 @@ namespace Bit.App.Pages public Entry MasterPasswordEntry { get; set; } - protected override async void OnAppearing() + protected override async void OnNavigatedTo(NavigatedToEventArgs args) { - base.OnAppearing(); + base.OnNavigatedTo(args); + + //IsInitialized is used as a workaround to avoid duplicate initialization issues because of OnNavigatedTo being called twice. + if (HasInitialized) { return; } + HasInitialized = true; + _broadcasterService.Subscribe(nameof(LoginPage), message => { if (message.Command == Constants.ClearSensitiveFields) { - Device.BeginInvokeOnMainThread(_vm.ResetPasswordField); + MainThread.BeginInvokeOnMainThread(_vm.ResetPasswordField); } }); _mainContent.Content = _mainLayout; @@ -96,13 +94,20 @@ namespace Bit.App.Pages RequestFocus(_masterPassword); _inputFocused = true; } - // TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes - if (Device.RuntimePlatform == Device.Android && !_vm.CanRemoveAccount) + if (DeviceInfo.Platform == DevicePlatform.Android && !_vm.CanRemoveAccount) { ToolbarItems.Add(_removeAccount); } } + protected override void OnNavigatedFrom(NavigatedFromEventArgs args) + { + base.OnNavigatedFrom(args); + + _accountAvatar?.OnDisappearing(); + _broadcasterService.Unsubscribe(nameof(LoginPage)); + } + protected override bool OnBackButtonPressed() { if (_accountListOverlay.IsVisible) @@ -113,14 +118,6 @@ namespace Bit.App.Pages return false; } - protected override void OnDisappearing() - { - base.OnDisappearing(); - - _accountAvatar?.OnDisappearing(); - _broadcasterService.Unsubscribe(nameof(LoginPage)); - } - private async void LogIn_Clicked(object sender, EventArgs e) { if (DoOnce()) diff --git a/src/Core/Pages/Accounts/LoginPageViewModel.cs b/src/Core/Pages/Accounts/LoginPageViewModel.cs index 595aaddf0..214f3d96a 100644 --- a/src/Core/Pages/Accounts/LoginPageViewModel.cs +++ b/src/Core/Pages/Accounts/LoginPageViewModel.cs @@ -155,8 +155,6 @@ namespace Bit.App.Pages { try { - // TODO: [MAUI-Migration] added delay or the modal navigation doesn't happen because of modal-loading is shown - await Task.Delay(1000); await _deviceActionService.ShowLoadingAsync(AppResources.Loading); await _stateService.SetPreLoginEmailAsync(Email); await AccountSwitchingOverlayViewModel.RefreshAccountViewsAsync(); diff --git a/src/Core/Pages/Accounts/LoginSsoPage.xaml.cs b/src/Core/Pages/Accounts/LoginSsoPage.xaml.cs index 53b90a3bd..20bcdeb2a 100644 --- a/src/Core/Pages/Accounts/LoginSsoPage.xaml.cs +++ b/src/Core/Pages/Accounts/LoginSsoPage.xaml.cs @@ -1,11 +1,7 @@ -using System; -using System.Threading.Tasks; -using Bit.App.Models; +using Bit.App.Models; using Bit.App.Utilities; using Bit.Core.Abstractions; using Bit.Core.Utilities; -using Microsoft.Maui.Controls; -using Microsoft.Maui; namespace Bit.App.Pages { @@ -24,28 +20,44 @@ namespace Bit.App.Pages InitializeComponent(); _vm = BindingContext as LoginSsoPageViewModel; _vm.Page = this; - _vm.StartTwoFactorAction = () => Device.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync()); + _vm.StartTwoFactorAction = () => MainThread.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync()); _vm.StartSetPasswordAction = () => - Device.BeginInvokeOnMainThread(async () => await StartSetPasswordAsync()); - _vm.SsoAuthSuccessAction = () => Device.BeginInvokeOnMainThread(async () => await SsoAuthSuccessAsync()); + MainThread.BeginInvokeOnMainThread(async () => await StartSetPasswordAsync()); + _vm.SsoAuthSuccessAction = () => MainThread.BeginInvokeOnMainThread(async () => await SsoAuthSuccessAsync()); _vm.UpdateTempPasswordAction = - () => Device.BeginInvokeOnMainThread(async () => await UpdateTempPasswordAsync()); + () => MainThread.BeginInvokeOnMainThread(async () => await UpdateTempPasswordAsync()); _vm.StartDeviceApprovalOptionsAction = - () => Device.BeginInvokeOnMainThread(async () => await StartDeviceApprovalOptionsAsync()); + () => MainThread.BeginInvokeOnMainThread(async () => await StartDeviceApprovalOptionsAsync()); _vm.CloseAction = async () => { await Navigation.PopModalAsync(); }; - // TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes - if (Device.RuntimePlatform == Device.Android) + + if (DeviceInfo.Platform == DevicePlatform.Android) { ToolbarItems.RemoveAt(0); } } - protected override async void OnAppearing() + protected override async void OnNavigatedTo(NavigatedToEventArgs args) { - base.OnAppearing(); + base.OnNavigatedTo(args); + + //IsInitialized is used as a workaround to avoid duplicate initialization issues because of OnNavigatedTo being called twice. + if (HasInitialized) { return; } + HasInitialized = true; + + await _vm.InitAsync(); + if (string.IsNullOrWhiteSpace(_vm.OrgIdentifier)) + { + RequestFocus(_orgIdentifier); + } + } + + protected override async void OnNavigatedFrom(NavigatedFromEventArgs args) + { + base.OnNavigatedFrom(args); + await _vm.InitAsync(); if (string.IsNullOrWhiteSpace(_vm.OrgIdentifier)) { diff --git a/src/Core/Pages/BaseContentPage.cs b/src/Core/Pages/BaseContentPage.cs index 0ad77c0a6..52077d8ed 100644 --- a/src/Core/Pages/BaseContentPage.cs +++ b/src/Core/Pages/BaseContentPage.cs @@ -25,13 +25,16 @@ namespace Bit.App.Pages } } + //IsInitialized is used as a workaround to avoid duplicate initialization issues for some pages where OnNavigatedTo is called twice. + protected bool HasInitialized { get; set; } + public DateTime? LastPageAction { get; set; } public bool IsThemeDirty { get; set; } - protected override async void OnAppearing() + protected override async void OnNavigatedTo(NavigatedToEventArgs args) { - base.OnAppearing(); + base.OnNavigatedTo(args); if (IsThemeDirty) {