Fix crash when trying to Focus an Entry from a background thread and improved the code so there are fewer direct access from the VM to the View (#1879)

This commit is contained in:
Federico Maccaroni 2022-07-05 17:37:06 -03:00 committed by GitHub
parent a6ddc2496f
commit dbc1e5ea3e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 30 deletions

View file

@ -25,8 +25,6 @@ namespace Bit.App.Pages
_vm = BindingContext as LockPageViewModel; _vm = BindingContext as LockPageViewModel;
_vm.Page = this; _vm.Page = this;
_vm.UnlockedAction = () => Device.BeginInvokeOnMainThread(async () => await UnlockedAsync()); _vm.UnlockedAction = () => Device.BeginInvokeOnMainThread(async () => await UnlockedAsync());
MasterPasswordEntry = _masterPassword;
PinEntry = _pin;
if (Device.RuntimePlatform == Device.iOS) if (Device.RuntimePlatform == Device.iOS)
{ {
@ -38,8 +36,17 @@ namespace Bit.App.Pages
} }
} }
public Entry MasterPasswordEntry { get; set; } public Entry SecretEntry
public Entry PinEntry { get; set; } {
get
{
if (_vm?.PinLock ?? false)
{
return _pin;
}
return _masterPassword;
}
}
public async Task PromptBiometricAfterResumeAsync() public async Task PromptBiometricAfterResumeAsync()
{ {
@ -70,16 +77,12 @@ namespace Bit.App.Pages
_vm.AvatarImageSource = await GetAvatarImageSourceAsync(); _vm.AvatarImageSource = await GetAvatarImageSourceAsync();
await _vm.InitAsync(); await _vm.InitAsync();
_vm.FocusSecretEntry += PerformFocusSecretEntry;
if (!_vm.BiometricLock) if (!_vm.BiometricLock)
{ {
if (_vm.PinLock) RequestFocus(SecretEntry);
{
RequestFocus(PinEntry);
}
else
{
RequestFocus(MasterPasswordEntry);
}
} }
else else
{ {
@ -99,6 +102,18 @@ namespace Bit.App.Pages
} }
} }
private void PerformFocusSecretEntry(int? cursorPosition)
{
Device.BeginInvokeOnMainThread(() =>
{
SecretEntry.Focus();
if (cursorPosition.HasValue)
{
SecretEntry.CursorPosition = cursorPosition.Value;
}
});
}
protected override bool OnBackButtonPressed() protected override bool OnBackButtonPressed()
{ {
if (_accountListOverlay.IsVisible) if (_accountListOverlay.IsVisible)

View file

@ -10,6 +10,7 @@ using Bit.Core.Enums;
using Bit.Core.Models.Domain; using Bit.Core.Models.Domain;
using Bit.Core.Models.Request; using Bit.Core.Models.Request;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Xamarin.CommunityToolkit.Helpers;
using Xamarin.Forms; using Xamarin.Forms;
namespace Bit.App.Pages namespace Bit.App.Pages
@ -27,6 +28,7 @@ namespace Bit.App.Pages
private readonly IBiometricService _biometricService; private readonly IBiometricService _biometricService;
private readonly IKeyConnectorService _keyConnectorService; private readonly IKeyConnectorService _keyConnectorService;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly WeakEventManager<int?> _secretEntryFocusWeakEventManager = new WeakEventManager<int?>();
private string _email; private string _email;
private bool _showPassword; private bool _showPassword;
@ -133,6 +135,11 @@ namespace Bit.App.Pages
public string MasterPassword { get; set; } public string MasterPassword { get; set; }
public string Pin { get; set; } public string Pin { get; set; }
public Action UnlockedAction { get; set; } public Action UnlockedAction { get; set; }
public event Action<int?> FocusSecretEntry
{
add => _secretEntryFocusWeakEventManager.AddEventHandler(value);
remove => _secretEntryFocusWeakEventManager.RemoveEventHandler(value);
}
public async Task InitAsync() public async Task InitAsync()
{ {
@ -346,11 +353,8 @@ namespace Bit.App.Pages
public void TogglePassword() public void TogglePassword()
{ {
ShowPassword = !ShowPassword; ShowPassword = !ShowPassword;
var page = (Page as LockPage); var secret = PinLock ? Pin : MasterPassword;
var entry = PinLock ? page.PinEntry : page.MasterPasswordEntry; _secretEntryFocusWeakEventManager.RaiseEvent(string.IsNullOrEmpty(secret) ? 0 : secret.Length, nameof(FocusSecretEntry));
var str = PinLock ? Pin : MasterPassword;
entry.Focus();
entry.CursorPosition = String.IsNullOrEmpty(str) ? 0 : str.Length;
} }
public async Task PromptBiometricAsync() public async Task PromptBiometricAsync()
@ -361,18 +365,8 @@ namespace Bit.App.Pages
return; return;
} }
var success = await _platformUtilsService.AuthenticateBiometricAsync(null, var success = await _platformUtilsService.AuthenticateBiometricAsync(null,
PinLock ? AppResources.PIN : AppResources.MasterPassword, () => PinLock ? AppResources.PIN : AppResources.MasterPassword,
{ () => _secretEntryFocusWeakEventManager.RaiseEvent((int?)null, nameof(FocusSecretEntry)));
var page = Page as LockPage;
if (PinLock)
{
page.PinEntry.Focus();
}
else
{
page.MasterPasswordEntry.Focus();
}
});
await _stateService.SetBiometricLockedAsync(!success); await _stateService.SetBiometricLockedAsync(!success);
if (success) if (success)
{ {