Bitwarden-app-android-iphon.../src/App/Controls/AccountSwitchingOverlay/AccountSwitchingOverlayView...

195 lines
6.0 KiB
C#

using System;
using System.Threading.Tasks;
using System.Windows.Input;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public partial class AccountSwitchingOverlayView : ContentView
{
public static readonly BindableProperty MainPageProperty = BindableProperty.Create(
nameof(MainPage),
typeof(ContentPage),
typeof(AccountSwitchingOverlayView),
defaultBindingMode: BindingMode.OneWay);
public static readonly BindableProperty MainFabProperty = BindableProperty.Create(
nameof(MainFab),
typeof(View),
typeof(AccountSwitchingOverlayView),
defaultBindingMode: BindingMode.OneWay);
public ContentPage MainPage
{
get => (ContentPage)GetValue(MainPageProperty);
set => SetValue(MainPageProperty, value);
}
public View MainFab
{
get => (View)GetValue(MainFabProperty);
set => SetValue(MainFabProperty, value);
}
readonly LazyResolve<ILogger> _logger = new LazyResolve<ILogger>("logger");
public AccountSwitchingOverlayView()
{
InitializeComponent();
ToggleVisibililtyCommand = new AsyncCommand(ToggleVisibilityAsync,
onException: ex => _logger.Value.Exception(ex),
allowsMultipleExecutions: false);
SelectAccountCommand = new AsyncCommand<AccountViewCellViewModel>(SelectAccountAsync,
onException: ex => _logger.Value.Exception(ex),
allowsMultipleExecutions: false);
LongPressAccountCommand = new AsyncCommand<AccountViewCellViewModel>(LongPressAccountAsync,
onException: ex => _logger.Value.Exception(ex),
allowsMultipleExecutions: false);
}
public AccountSwitchingOverlayViewModel ViewModel => BindingContext as AccountSwitchingOverlayViewModel;
public ICommand ToggleVisibililtyCommand { get; }
public ICommand SelectAccountCommand { get; }
public ICommand LongPressAccountCommand { get; }
public int AccountListRowHeight => Device.RuntimePlatform == Device.Android ? 74 : 70;
public bool LongPressAccountEnabled { get; set; } = true;
public Action AfterHide { get; set; }
public async Task ToggleVisibilityAsync()
{
if (IsVisible)
{
await HideAsync();
}
else
{
await ShowAsync();
}
}
public async Task ShowAsync()
{
if (ViewModel == null)
{
return;
}
await ViewModel.RefreshAccountViewsAsync();
await Device.InvokeOnMainThreadAsync(async () =>
{
// start listView in default (off-screen) position
await _accountListContainer.TranslateTo(0, _accountListContainer.Height * -1, 0);
// re-measure in case accounts have been removed without changing screens
if (ViewModel.AccountViews != null)
{
_accountListView.HeightRequest = AccountListRowHeight * ViewModel.AccountViews.Count;
}
// set overlay opacity to zero before making visible and start fade-in
Opacity = 0;
IsVisible = true;
this.FadeTo(1, 100);
if (Device.RuntimePlatform == Device.Android && MainFab != null)
{
// start fab fade-out
MainFab.FadeTo(0, 200);
}
// slide account list into view
await _accountListContainer.TranslateTo(0, 0, 200, Easing.SinOut);
});
}
public async Task HideAsync()
{
if (!IsVisible)
{
// already hidden, don't animate again
return;
}
// Not all animations are awaited. This is intentional to allow multiple simultaneous animations.
await Device.InvokeOnMainThreadAsync(async () =>
{
// start overlay fade-out
this.FadeTo(0, 200);
if (Device.RuntimePlatform == Device.Android && MainFab != null)
{
// start fab fade-in
MainFab.FadeTo(1, 200);
}
// slide account list out of view
await _accountListContainer.TranslateTo(0, _accountListContainer.Height * -1, 200, Easing.SinIn);
// remove overlay
IsVisible = false;
AfterHide?.Invoke();
});
}
private async void FreeSpaceOverlay_Tapped(object sender, EventArgs e)
{
try
{
await HideAsync();
}
catch (Exception ex)
{
_logger.Value.Exception(ex);
}
}
private async Task SelectAccountAsync(AccountViewCellViewModel item)
{
try
{
await Task.Delay(100);
await HideAsync();
ViewModel?.SelectAccountCommand?.Execute(item);
}
catch (Exception ex)
{
_logger.Value.Exception(ex);
}
}
private async Task LongPressAccountAsync(AccountViewCellViewModel item)
{
if (!LongPressAccountEnabled || !item.IsAccount)
{
return;
}
try
{
await Task.Delay(100);
await HideAsync();
ViewModel?.LongPressAccountCommand?.Execute(
new Tuple<ContentPage, AccountViewCellViewModel>(MainPage, item));
}
catch (Exception ex)
{
_logger.Value.Exception(ex);
}
}
}
}