PM-3350 Fixed iOS Extensions navigation to several pages and improved avoiding duplicate calls to OnNavigatedTo

This commit is contained in:
Federico Maccaroni 2023-11-14 13:43:59 -03:00
parent 5f12bb9747
commit df4d89cd52
No known key found for this signature in database
GPG key ID: 5D233F8F2B034536
13 changed files with 145 additions and 179 deletions

View file

@ -1,10 +1,6 @@
using System; using Bit.Core.Abstractions;
using System.Threading.Tasks;
using Bit.Core.Resources.Localization; using Bit.Core.Resources.Localization;
using Bit.Core.Abstractions;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Microsoft.Maui.Controls;
using Microsoft.Maui;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@ -19,11 +15,10 @@ namespace Bit.App.Pages
InitializeComponent(); InitializeComponent();
_vm = BindingContext as EnvironmentPageViewModel; _vm = BindingContext as EnvironmentPageViewModel;
_vm.Page = this; _vm.Page = this;
// 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 ANDROID
{ ToolbarItems.RemoveAt(0);
ToolbarItems.RemoveAt(0); #endif
}
_webVaultEntry.ReturnType = ReturnType.Next; _webVaultEntry.ReturnType = ReturnType.Next;
_webVaultEntry.ReturnCommand = new Command(() => _apiEntry.Focus()); _webVaultEntry.ReturnCommand = new Command(() => _apiEntry.Focus());
@ -31,7 +26,7 @@ namespace Bit.App.Pages
_apiEntry.ReturnCommand = new Command(() => _identityEntry.Focus()); _apiEntry.ReturnCommand = new Command(() => _identityEntry.Focus());
_identityEntry.ReturnType = ReturnType.Next; _identityEntry.ReturnType = ReturnType.Next;
_identityEntry.ReturnCommand = new Command(() => _iconsEntry.Focus()); _identityEntry.ReturnCommand = new Command(() => _iconsEntry.Focus());
_vm.SubmitSuccessAction = () => Device.BeginInvokeOnMainThread(async () => await SubmitSuccessAsync()); _vm.SubmitSuccessAction = () => MainThread.BeginInvokeOnMainThread(async () => await SubmitSuccessAsync());
_vm.CloseAction = async () => _vm.CloseAction = async () =>
{ {
await Navigation.PopModalAsync(); await Navigation.PopModalAsync();

View file

@ -1,11 +1,7 @@
using System; using Bit.App.Models;
using System.Threading.Tasks;
using Bit.App.Models;
using Bit.App.Utilities; using Bit.App.Utilities;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Microsoft.Maui.Controls;
using Microsoft.Maui;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@ -20,16 +16,16 @@ namespace Bit.App.Pages
public HomePage(AppOptions appOptions = null) public HomePage(AppOptions appOptions = null)
{ {
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService"); _broadcasterService = ServiceContainer.Resolve<IBroadcasterService>();
_appOptions = appOptions; _appOptions = appOptions;
InitializeComponent(); InitializeComponent();
_vm = BindingContext as HomeViewModel; _vm = BindingContext as HomeViewModel;
_vm.Page = this; _vm.Page = this;
_vm.ShowCancelButton = _appOptions?.IosExtension ?? false; _vm.ShowCancelButton = _appOptions?.IosExtension ?? false;
_vm.StartLoginAction = async () => await StartLoginAsync(); _vm.StartLoginAction = async () => await StartLoginAsync();
_vm.StartRegisterAction = () => Device.BeginInvokeOnMainThread(async () => await StartRegisterAsync()); _vm.StartRegisterAction = () => MainThread.BeginInvokeOnMainThread(async () => await StartRegisterAsync());
_vm.StartSsoLoginAction = () => Device.BeginInvokeOnMainThread(async () => await StartSsoLoginAsync()); _vm.StartSsoLoginAction = () => MainThread.BeginInvokeOnMainThread(async () => await StartSsoLoginAsync());
_vm.StartEnvironmentAction = () => Device.BeginInvokeOnMainThread(async () => await StartEnvironmentAsync()); _vm.StartEnvironmentAction = () => MainThread.BeginInvokeOnMainThread(async () => await StartEnvironmentAsync());
_vm.CloseAction = async () => _vm.CloseAction = async () =>
{ {
await _accountListOverlay.HideAsync(); await _accountListOverlay.HideAsync();
@ -53,28 +49,28 @@ namespace Bit.App.Pages
await Navigation.PushModalAsync(new NavigationPage(new LoginPage(email, _appOptions))); await Navigation.PushModalAsync(new NavigationPage(new LoginPage(email, _appOptions)));
} }
protected override async void OnAppearing() protected override async void OnNavigatedTo(NavigatedToEventArgs args)
{ {
base.OnAppearing(); base.OnNavigatedTo(args);
_mainContent.Content = _mainLayout;
_accountAvatar?.OnAppearing(); await MainThread.InvokeOnMainThreadAsync(() => _mainContent.Content = _mainLayout);
if (!_appOptions?.HideAccountSwitcher ?? false)
{
_vm.AvatarImageSource = await GetAvatarImageSourceAsync(false);
}
_broadcasterService.Subscribe(nameof(HomePage), (message) =>
{
if (message.Command is ThemeManager.UPDATED_THEME_MESSAGE_KEY)
{
Device.BeginInvokeOnMainThread(() =>
{
UpdateLogo();
});
}
});
try try
{ {
_accountAvatar?.OnAppearing();
if (!_appOptions?.HideAccountSwitcher ?? false)
{
await MainThread.InvokeOnMainThreadAsync(async () => _vm.AvatarImageSource = await GetAvatarImageSourceAsync(false));
}
_broadcasterService.Subscribe(nameof(HomePage), (message) =>
{
if (message.Command is ThemeManager.UPDATED_THEME_MESSAGE_KEY)
{
MainThread.BeginInvokeOnMainThread(UpdateLogo);
}
});
await _vm.UpdateEnvironment(); await _vm.UpdateEnvironment();
} }
catch (Exception ex) catch (Exception ex)
@ -83,6 +79,14 @@ namespace Bit.App.Pages
} }
} }
protected override void OnNavigatingFrom(NavigatingFromEventArgs args)
{
base.OnNavigatingFrom(args);
_broadcasterService?.Unsubscribe(nameof(HomePage));
_accountAvatar?.OnDisappearing();
}
protected override bool OnBackButtonPressed() protected override bool OnBackButtonPressed()
{ {
if (_accountListOverlay.IsVisible) if (_accountListOverlay.IsVisible)
@ -93,13 +97,6 @@ namespace Bit.App.Pages
return false; return false;
} }
protected override void OnDisappearing()
{
base.OnDisappearing();
_broadcasterService.Unsubscribe(nameof(HomePage));
_accountAvatar?.OnDisappearing();
}
private void UpdateLogo() private void UpdateLogo()
{ {
_logo.Source = !ThemeManager.UsingLightTheme ? "logo_white.png" : "logo.png"; _logo.Source = !ThemeManager.UsingLightTheme ? "logo_white.png" : "logo.png";

View file

@ -1,18 +1,12 @@
using System; using Bit.App.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
using Bit.App.Models;
using Bit.App.Utilities; using Bit.App.Utilities;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Microsoft.Maui.Controls;
using Microsoft.Maui;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
public partial class LoginApproveDevicePage : BaseContentPage public partial class LoginApproveDevicePage : BaseContentPage
{ {
private readonly LoginApproveDeviceViewModel _vm; private readonly LoginApproveDeviceViewModel _vm;
private readonly AppOptions _appOptions; private readonly AppOptions _appOptions;
@ -28,9 +22,11 @@ namespace Bit.App.Pages
_appOptions = appOptions; _appOptions = appOptions;
} }
protected override void OnAppearing() protected override bool ShouldCheckToPreventOnNavigatedToCalledTwice => true;
protected override async Task InitOnNavigatedToAsync()
{ {
_vm.InitAsync(); await _vm.InitAsync();
} }
private async Task ContinueToVaultAsync() private async Task ContinueToVaultAsync()
@ -62,4 +58,3 @@ namespace Bit.App.Pages
} }
} }
} }

View file

@ -64,16 +64,12 @@ namespace Bit.App.Pages
} }
} }
protected override bool ShouldCheckToPreventOnNavigatedToCalledTwice => true;
public Entry MasterPasswordEntry { get; set; } public Entry MasterPasswordEntry { get; set; }
protected override async void OnNavigatedTo(NavigatedToEventArgs args) protected override async Task InitOnNavigatedToAsync()
{ {
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 => _broadcasterService.Subscribe(nameof(LoginPage), message =>
{ {
if (message.Command == Constants.ClearSensitiveFields) if (message.Command == Constants.ClearSensitiveFields)

View file

@ -1,11 +1,6 @@
using System; using Bit.App.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
using Bit.App.Models;
using Bit.App.Utilities; using Bit.App.Utilities;
using Bit.Core.Enums; using Bit.Core.Enums;
using Microsoft.Maui.Controls;
using Microsoft.Maui;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@ -23,23 +18,25 @@ namespace Bit.App.Pages
_vm.Email = email; _vm.Email = email;
_vm.AuthRequestType = authRequestType; _vm.AuthRequestType = authRequestType;
_vm.AuthingWithSso = authingWithSso; _vm.AuthingWithSso = authingWithSso;
_vm.StartTwoFactorAction = () => Device.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync()); _vm.StartTwoFactorAction = () => MainThread.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync());
_vm.LogInSuccessAction = () => Device.BeginInvokeOnMainThread(async () => await LogInSuccessAsync()); _vm.LogInSuccessAction = () => MainThread.BeginInvokeOnMainThread(async () => await LogInSuccessAsync());
_vm.UpdateTempPasswordAction = () => Device.BeginInvokeOnMainThread(async () => await UpdateTempPasswordAsync()); _vm.UpdateTempPasswordAction = () => MainThread.BeginInvokeOnMainThread(async () => await UpdateTempPasswordAsync());
_vm.CloseAction = () => { Navigation.PopModalAsync(); }; _vm.CloseAction = () => { Navigation.PopModalAsync(); };
_vm.CreatePasswordlessLoginCommand.Execute(null); _vm.CreatePasswordlessLoginCommand.Execute(null);
} }
protected override void OnAppearing() protected override bool ShouldCheckToPreventOnNavigatedToCalledTwice => true;
protected override Task InitOnNavigatedToAsync()
{ {
base.OnAppearing();
_vm.StartCheckLoginRequestStatus(); _vm.StartCheckLoginRequestStatus();
return Task.CompletedTask;
} }
protected override void OnDisappearing() protected override void OnNavigatedFrom(NavigatedFromEventArgs args)
{ {
base.OnDisappearing(); base.OnNavigatedFrom(args);
_vm.StopCheckLoginRequestStatus(); _vm.StopCheckLoginRequestStatus();
} }
@ -66,4 +63,3 @@ namespace Bit.App.Pages
} }
} }
} }

View file

@ -1,26 +1,14 @@
using System; using System.Windows.Input;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.Core.Resources.Localization;
using Bit.App.Utilities; using Bit.App.Utilities;
using Bit.Core;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Exceptions; using Bit.Core.Exceptions;
using Bit.Core.Models.Domain; using Bit.Core.Models.Domain;
using Bit.Core.Models.Response; using Bit.Core.Models.Response;
using Bit.Core.Services; using Bit.Core.Resources.Localization;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Microsoft.Maui.Controls;
using Microsoft.Maui;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
public class LoginPasswordlessRequestViewModel : CaptchaProtectedViewModel public class LoginPasswordlessRequestViewModel : CaptchaProtectedViewModel
@ -72,7 +60,7 @@ namespace Bit.App.Pages
onException: ex => HandleException(ex), onException: ex => HandleException(ex),
allowsMultipleExecutions: false); allowsMultipleExecutions: false);
CloseCommand = new AsyncCommand(() => Device.InvokeOnMainThreadAsync(CloseAction), CloseCommand = new AsyncCommand(() => MainThread.InvokeOnMainThreadAsync(CloseAction),
onException: _logger.Exception, onException: _logger.Exception,
allowsMultipleExecutions: false); allowsMultipleExecutions: false);
} }

View file

@ -39,25 +39,10 @@ namespace Bit.App.Pages
} }
} }
protected override async void OnNavigatedTo(NavigatedToEventArgs args) protected override bool ShouldCheckToPreventOnNavigatedToCalledTwice => true;
protected override async Task InitOnNavigatedToAsync()
{ {
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(); await _vm.InitAsync();
if (string.IsNullOrWhiteSpace(_vm.OrgIdentifier)) if (string.IsNullOrWhiteSpace(_vm.OrgIdentifier))
{ {

View file

@ -1,9 +1,4 @@
using System; namespace Bit.App.Pages
using System.Threading.Tasks;
using Microsoft.Maui.Controls;
using Microsoft.Maui;
namespace Bit.App.Pages
{ {
public partial class RegisterPage : BaseContentPage public partial class RegisterPage : BaseContentPage
{ {
@ -16,18 +11,17 @@ namespace Bit.App.Pages
InitializeComponent(); InitializeComponent();
_vm = BindingContext as RegisterPageViewModel; _vm = BindingContext as RegisterPageViewModel;
_vm.Page = this; _vm.Page = this;
_vm.RegistrationSuccess = () => Device.BeginInvokeOnMainThread(async () => await RegistrationSuccessAsync(homePage)); _vm.RegistrationSuccess = () => MainThread.BeginInvokeOnMainThread(async () => await RegistrationSuccessAsync(homePage));
_vm.CloseAction = async () => _vm.CloseAction = async () =>
{ {
await Navigation.PopModalAsync(); await Navigation.PopModalAsync();
}; };
MasterPasswordEntry = _masterPassword; MasterPasswordEntry = _masterPassword;
ConfirmMasterPasswordEntry = _confirmMasterPassword; ConfirmMasterPasswordEntry = _confirmMasterPassword;
// 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 ANDROID
{ ToolbarItems.RemoveAt(0);
ToolbarItems.RemoveAt(0); #endif
}
_email.ReturnType = ReturnType.Next; _email.ReturnType = ReturnType.Next;
_email.ReturnCommand = new Command(() => _masterPassword.Focus()); _email.ReturnCommand = new Command(() => _masterPassword.Focus());
@ -40,14 +34,17 @@ namespace Bit.App.Pages
public Entry MasterPasswordEntry { get; set; } public Entry MasterPasswordEntry { get; set; }
public Entry ConfirmMasterPasswordEntry { get; set; } public Entry ConfirmMasterPasswordEntry { get; set; }
protected override void OnAppearing() protected override bool ShouldCheckToPreventOnNavigatedToCalledTwice => true;
protected override Task InitOnNavigatedToAsync()
{ {
base.OnAppearing();
if (!_inputFocused) if (!_inputFocused)
{ {
RequestFocus(_email); RequestFocus(_email);
_inputFocused = true; _inputFocused = true;
} }
return Task.CompletedTask;
} }
private async void Submit_Clicked(object sender, EventArgs e) private async void Submit_Clicked(object sender, EventArgs e)

View file

@ -1,9 +1,5 @@
using System; using Bit.App.Models;
using System.Threading.Tasks;
using Bit.App.Models;
using Bit.App.Utilities; using Bit.App.Utilities;
using Microsoft.Maui.Controls;
using Microsoft.Maui;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@ -19,17 +15,16 @@ namespace Bit.App.Pages
_vm = BindingContext as SetPasswordPageViewModel; _vm = BindingContext as SetPasswordPageViewModel;
_vm.Page = this; _vm.Page = this;
_vm.SetPasswordSuccessAction = _vm.SetPasswordSuccessAction =
() => Device.BeginInvokeOnMainThread(async () => await SetPasswordSuccessAsync()); () => MainThread.BeginInvokeOnMainThread(async () => await SetPasswordSuccessAsync());
_vm.CloseAction = async () => _vm.CloseAction = async () =>
{ {
await Navigation.PopModalAsync(); await Navigation.PopModalAsync();
}; };
_vm.OrgIdentifier = orgIdentifier; _vm.OrgIdentifier = orgIdentifier;
// 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 ANDROID
{ ToolbarItems.RemoveAt(0);
ToolbarItems.RemoveAt(0); #endif
}
MasterPasswordEntry = _masterPassword; MasterPasswordEntry = _masterPassword;
ConfirmMasterPasswordEntry = _confirmMasterPassword; ConfirmMasterPasswordEntry = _confirmMasterPassword;
@ -43,9 +38,10 @@ namespace Bit.App.Pages
public Entry MasterPasswordEntry { get; set; } public Entry MasterPasswordEntry { get; set; }
public Entry ConfirmMasterPasswordEntry { get; set; } public Entry ConfirmMasterPasswordEntry { get; set; }
protected override async void OnAppearing() protected override bool ShouldCheckToPreventOnNavigatedToCalledTwice => true;
protected override async Task InitOnNavigatedToAsync()
{ {
base.OnAppearing();
await _vm.InitAsync(); await _vm.InitAsync();
RequestFocus(_masterPassword); RequestFocus(_masterPassword);
} }
@ -58,7 +54,7 @@ namespace Bit.App.Pages
} }
} }
private async void Close_Clicked(object sender, EventArgs e) private void Close_Clicked(object sender, EventArgs e)
{ {
if (DoOnce()) if (DoOnce())
{ {

View file

@ -22,8 +22,8 @@ namespace Bit.App.Pages
SetActivityIndicator(); SetActivityIndicator();
_appOptions = appOptions; _appOptions = appOptions;
_orgIdentifier = orgIdentifier; _orgIdentifier = orgIdentifier;
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService"); _broadcasterService = ServiceContainer.Resolve<IBroadcasterService>();
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService"); _messagingService = ServiceContainer.Resolve<IMessagingService>();
_vm = BindingContext as TwoFactorPageViewModel; _vm = BindingContext as TwoFactorPageViewModel;
_vm.Page = this; _vm.Page = this;
_vm.AuthingWithSso = authingWithSso ?? false; _vm.AuthingWithSso = authingWithSso ?? false;
@ -40,25 +40,21 @@ namespace Bit.App.Pages
_vm.CloseAction = async () => await Navigation.PopModalAsync(); _vm.CloseAction = async () => await Navigation.PopModalAsync();
DuoWebView = _duoWebView; DuoWebView = _duoWebView;
if (DeviceInfo.Platform == DevicePlatform.Android) #if ANDROID
{ ToolbarItems.Remove(_cancelItem);
ToolbarItems.Remove(_cancelItem); ToolbarItems.Add(_useAnotherTwoStepMethod);
} #else
if (DeviceInfo.Platform == DevicePlatform.iOS)
{ ToolbarItems.Add(_moreItem);
ToolbarItems.Add(_moreItem); #endif
}
else
{
ToolbarItems.Add(_useAnotherTwoStepMethod);
}
} }
public HybridWebView DuoWebView { get; set; } public HybridWebView DuoWebView { get; set; }
protected override async void OnAppearing() protected override bool ShouldCheckToPreventOnNavigatedToCalledTwice => true;
protected override async Task InitOnNavigatedToAsync()
{ {
base.OnAppearing();
_broadcasterService.Subscribe(nameof(TwoFactorPage), (message) => _broadcasterService.Subscribe(nameof(TwoFactorPage), (message) =>
{ {
if (message.Command == "gotYubiKeyOTP") if (message.Command == "gotYubiKeyOTP")
@ -101,10 +97,11 @@ namespace Bit.App.Pages
return Task.FromResult(0); return Task.FromResult(0);
}); });
} }
protected override void OnDisappearing() protected override void OnNavigatedFrom(NavigatedFromEventArgs args)
{ {
base.OnDisappearing(); base.OnNavigatedFrom(args);
if (!_vm.YubikeyMethod) if (!_vm.YubikeyMethod)
{ {
_messagingService.Send("listenYubiKeyOTP", false); _messagingService.Send("listenYubiKeyOTP", false);

View file

@ -1,9 +1,6 @@
using System; using Bit.Core.Abstractions;
using Bit.Core.Resources.Localization; using Bit.Core.Resources.Localization;
using Bit.Core.Abstractions;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Microsoft.Maui.Controls;
using Microsoft.Maui;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@ -17,8 +14,8 @@ namespace Bit.App.Pages
public UpdateTempPasswordPage() public UpdateTempPasswordPage()
{ {
// Service Init // Service Init
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService"); _messagingService = ServiceContainer.Resolve<IMessagingService>();
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService"); _platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>();
// Binding // Binding
InitializeComponent(); InitializeComponent();
@ -30,9 +27,9 @@ namespace Bit.App.Pages
// Actions Declaration // Actions Declaration
_vm.LogOutAction = () => _vm.LogOutAction = () =>
{ {
_messagingService.Send("logout"); _messagingService.Send(AccountsManagerMessageCommands.LOGOUT);
}; };
_vm.UpdateTempPasswordSuccessAction = () => Device.BeginInvokeOnMainThread(UpdateTempPasswordSuccess); _vm.UpdateTempPasswordSuccessAction = () => MainThread.BeginInvokeOnMainThread(UpdateTempPasswordSuccess);
// Link fields that will be referenced in codebehind // Link fields that will be referenced in codebehind
MasterPasswordEntry = _masterPassword; MasterPasswordEntry = _masterPassword;
@ -48,9 +45,10 @@ namespace Bit.App.Pages
public Entry MasterPasswordEntry { get; set; } public Entry MasterPasswordEntry { get; set; }
public Entry ConfirmMasterPasswordEntry { get; set; } public Entry ConfirmMasterPasswordEntry { get; set; }
protected override async void OnAppearing() protected override bool ShouldCheckToPreventOnNavigatedToCalledTwice => true;
protected override async Task InitOnNavigatedToAsync()
{ {
base.OnAppearing();
await LoadOnAppearedAsync(_mainLayout, true, async () => await LoadOnAppearedAsync(_mainLayout, true, async () =>
{ {
await _vm.InitAsync(true); await _vm.InitAsync(true);
@ -81,7 +79,7 @@ namespace Bit.App.Pages
private void UpdateTempPasswordSuccess() private void UpdateTempPasswordSuccess()
{ {
_messagingService.Send("logout"); _messagingService.Send(AccountsManagerMessageCommands.LOGOUT);
} }
} }
} }

View file

@ -3,8 +3,10 @@ using Bit.App.Controls;
using Bit.App.Utilities; using Bit.App.Utilities;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Utilities; using Bit.Core.Utilities;
#if IOS
using Microsoft.Maui.Controls.PlatformConfiguration; using Microsoft.Maui.Controls.PlatformConfiguration;
using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific; using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific;
#endif
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@ -16,22 +18,34 @@ namespace Bit.App.Pages
protected int ShowModalAnimationDelay = 400; protected int ShowModalAnimationDelay = 400;
protected int ShowPageAnimationDelay = 100; protected int ShowPageAnimationDelay = 100;
/// <summary>
/// Used as a workaround to avoid duplicate initialization issues for some pages where OnNavigatedTo is called twice.
/// </summary>
private bool _hasInitedOnNavigatedTo;
public BaseContentPage() public BaseContentPage()
{ {
if (DeviceInfo.Platform == DevicePlatform.iOS) #if IOS
{ On<iOS>().SetUseSafeArea(true);
On<iOS>().SetUseSafeArea(true); On<iOS>().SetModalPresentationStyle(UIModalPresentationStyle.FullScreen);
On<iOS>().SetModalPresentationStyle(UIModalPresentationStyle.FullScreen); #endif
}
} }
//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 DateTime? LastPageAction { get; set; }
public bool IsThemeDirty { get; set; } public bool IsThemeDirty { get; set; }
/// <summary>
/// This flag is used to see if check is needed to avoid duplicate calls of <see cref="OnNavigatedTo(NavigatedToEventArgs)"/>
/// Usually on modal navigation to the current page this flag should be <c>true</c>
/// Also this flag is added instead of directly checking for all pages to avoid potential issues on the app
/// and focusing only on the places where it's actually needed.
/// </summary>
/// <remarks>
/// This should be removed once MAUI fixes the issue of duplicate call to the method.
/// </remarks>
protected virtual bool ShouldCheckToPreventOnNavigatedToCalledTwice => false;
protected override async void OnNavigatedTo(NavigatedToEventArgs args) protected override async void OnNavigatedTo(NavigatedToEventArgs args)
{ {
base.OnNavigatedTo(args); base.OnNavigatedTo(args);
@ -42,6 +56,22 @@ namespace Bit.App.Pages
} }
await SaveActivityAsync(); await SaveActivityAsync();
if (ShouldCheckToPreventOnNavigatedToCalledTwice && _hasInitedOnNavigatedTo)
{
return;
}
_hasInitedOnNavigatedTo = true;
await InitOnNavigatedToAsync();
}
protected virtual Task InitOnNavigatedToAsync() => Task.CompletedTask;
protected override void OnNavigatedFrom(NavigatedFromEventArgs args)
{
base.OnNavigatedFrom(args);
_hasInitedOnNavigatedTo = false;
} }
public bool DoOnce(Action action = null, int milliseconds = 1000) public bool DoOnce(Action action = null, int milliseconds = 1000)

View file

@ -73,10 +73,6 @@
</Compile> </Compile>
<BundleResource Include="Resources\MaterialIcons_Regular.ttf" /> <BundleResource Include="Resources\MaterialIcons_Regular.ttf" />
<BundleResource Include="Resources\bwi-font.ttf" /> <BundleResource Include="Resources\bwi-font.ttf" />
<Compile Include="TestViewController.cs" />
<Compile Include="TestViewController.designer.cs">
<DependentUpon>TestViewController.cs</DependentUpon>
</Compile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Core\Core.csproj" /> <ProjectReference Include="..\Core\Core.csproj" />