mirror of
https://github.com/bitwarden/android.git
synced 2024-12-26 19:08:32 +03:00
PM-3349: Android
Added CustomTabbedPageHandler for Android to handle the tab "reselection" for PopToRoot. Commented support for Windows in App.csproj Disabled Interpreter on Android to avoid very slow app in Debug (during Login for example) Added some null checks that were causing crashes (on GeneratorPageVM and PickerVM) Minor TabsPage cleanup
This commit is contained in:
parent
d17789d5ee
commit
8b7f9b9fb3
6 changed files with 153 additions and 20 deletions
|
@ -2,9 +2,13 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net8.0-android;net8.0-ios</TargetFrameworks>
|
||||
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
|
||||
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
|
||||
<!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> -->
|
||||
|
||||
<!-- Uncomment to also build for Windows platform.-->
|
||||
<!--<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>-->
|
||||
|
||||
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
|
||||
<!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> -->
|
||||
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>Bit.App</RootNamespace>
|
||||
<UseMaui>true</UseMaui>
|
||||
|
@ -35,6 +39,17 @@
|
|||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>-->
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0-android|AnyCPU'">
|
||||
<AndroidEnableMultiDex>True</AndroidEnableMultiDex>
|
||||
<UseInterpreter>False</UseInterpreter>
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0-android|AnyCPU'">
|
||||
<AndroidEnableMultiDex>True</AndroidEnableMultiDex>
|
||||
<UseInterpreter>False</UseInterpreter>
|
||||
<DebugSymbols>False</DebugSymbols>
|
||||
<RunAOTCompilation>False</RunAOTCompilation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0-ios|AnyCPU'">
|
||||
<CreatePackage>false</CreatePackage>
|
||||
<RuntimeIdentifier>iossimulator-arm64</RuntimeIdentifier>
|
||||
|
|
|
@ -29,6 +29,8 @@ namespace Bit.App
|
|||
Bit.App.Handlers.StepperHandlerMappings.Setup();
|
||||
Bit.App.Handlers.TimePickerHandlerMappings.Setup();
|
||||
Bit.App.Handlers.ButtonHandlerMappings.Setup();
|
||||
|
||||
handlers.AddHandler(typeof(TabbedPage), typeof(Bit.App.Handlers.CustomTabbedPageHandler));
|
||||
#else
|
||||
iOS.Core.Handlers.ButtonHandlerMappings.Setup();
|
||||
iOS.Core.Handlers.DatePickerHandlerMappings.Setup();
|
||||
|
|
121
src/App/Platforms/Android/Handlers/CustomTabbedPageHandler.cs
Normal file
121
src/App/Platforms/Android/Handlers/CustomTabbedPageHandler.cs
Normal file
|
@ -0,0 +1,121 @@
|
|||
using AndroidX.AppCompat.View.Menu;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Utilities;
|
||||
using Google.Android.Material.BottomNavigation;
|
||||
using Microsoft.Maui.Handlers;
|
||||
|
||||
namespace Bit.App.Handlers
|
||||
{
|
||||
public partial class CustomTabbedPageHandler : TabbedViewHandler
|
||||
{
|
||||
private TabbedPage _tabbedPage;
|
||||
private BottomNavigationView _bottomNavigationView;
|
||||
private Android.Views.ViewGroup _bottomNavigationViewGroup;
|
||||
private ILogger _logger;
|
||||
|
||||
protected override void ConnectHandler(global::Android.Views.View platformView)
|
||||
{
|
||||
_logger = ServiceContainer.Resolve<ILogger>("logger");
|
||||
|
||||
if(VirtualView is TabbedPage tabbedPage)
|
||||
{
|
||||
_tabbedPage = tabbedPage;
|
||||
_tabbedPage.Loaded += TabbedPage_Loaded;
|
||||
}
|
||||
|
||||
base.ConnectHandler(platformView);
|
||||
}
|
||||
|
||||
private void TabbedPage_Loaded(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
//This layout should always be the same/fixed and therefore this should run with no issues. Nevertheless it's wrapped in try catch to avoid crashing in edge-case scenarios.
|
||||
_bottomNavigationViewGroup = (((sender as VisualElement).Handler as IPlatformViewHandler)
|
||||
.PlatformView
|
||||
.Parent
|
||||
.Parent as Android.Views.View)
|
||||
.FindViewById(Microsoft.Maui.Controls.Resource.Id.navigationlayout_bottomtabs) as Android.Views.ViewGroup;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Exception(ex);
|
||||
}
|
||||
|
||||
if(_bottomNavigationViewGroup == null) { return; }
|
||||
|
||||
//If TabbedPage still doesn't have items we set an event to wait for them
|
||||
if (_bottomNavigationViewGroup.ChildCount == 0)
|
||||
{
|
||||
_bottomNavigationViewGroup.ChildViewAdded += View_ChildViewAdded;
|
||||
}
|
||||
else
|
||||
{ //If we already have items we can start listening immediately
|
||||
var bottomTabs = _bottomNavigationViewGroup.GetChildAt(0);
|
||||
ListenToItemReselected(bottomTabs);
|
||||
}
|
||||
}
|
||||
|
||||
private void ListenToItemReselected(Android.Views.View bottomTabs)
|
||||
{
|
||||
if(bottomTabs is BottomNavigationView bottomNavigationView)
|
||||
{
|
||||
//If there was an older _bottomNavigationView for some reason we want to make sure to unregister
|
||||
if(_bottomNavigationView != null)
|
||||
{
|
||||
_bottomNavigationView.ItemReselected -= BottomNavigationView_ItemReselected;
|
||||
_bottomNavigationView = null;
|
||||
}
|
||||
|
||||
_bottomNavigationView = bottomNavigationView;
|
||||
_bottomNavigationView.ItemReselected += BottomNavigationView_ItemReselected;
|
||||
}
|
||||
}
|
||||
|
||||
private void View_ChildViewAdded(object sender, Android.Views.ViewGroup.ChildViewAddedEventArgs e)
|
||||
{
|
||||
//We shouldn't need this to be called anymore times so we can unregister to the events now
|
||||
if(_bottomNavigationViewGroup != null)
|
||||
{
|
||||
_bottomNavigationViewGroup.ChildViewAdded -= View_ChildViewAdded;
|
||||
}
|
||||
|
||||
var bottomTabs = e.Child;
|
||||
ListenToItemReselected(bottomTabs);
|
||||
}
|
||||
|
||||
private void BottomNavigationView_ItemReselected(object sender, Google.Android.Material.Navigation.NavigationBarView.ItemReselectedEventArgs e)
|
||||
{
|
||||
if(e.Item is MenuItemImpl item)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"Tab '{item.Title}' was reselected so we'll PopToRoot.");
|
||||
MainThread.BeginInvokeOnMainThread(async () => await _tabbedPage.CurrentPage.Navigation.PopToRootAsync());
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DisconnectHandler(global::Android.Views.View platformView)
|
||||
{
|
||||
if(_bottomNavigationViewGroup != null)
|
||||
{
|
||||
_bottomNavigationViewGroup.ChildViewAdded -= View_ChildViewAdded;
|
||||
_bottomNavigationViewGroup = null;
|
||||
}
|
||||
|
||||
if(_bottomNavigationView != null)
|
||||
{
|
||||
_bottomNavigationView.ItemReselected -= BottomNavigationView_ItemReselected;
|
||||
_bottomNavigationView = null;
|
||||
}
|
||||
|
||||
if(_tabbedPage != null)
|
||||
{
|
||||
_tabbedPage.Loaded -= TabbedPage_Loaded;
|
||||
_tabbedPage = null;
|
||||
}
|
||||
|
||||
_logger = null;
|
||||
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -338,7 +338,10 @@ namespace Bit.App.Pages
|
|||
|
||||
public string PlusAddressedEmail
|
||||
{
|
||||
get => _usernameOptions.PlusAddressedEmail;
|
||||
get
|
||||
{
|
||||
return _usernameOptions?.PlusAddressedEmail ?? string.Empty;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_usernameOptions != null && _usernameOptions.PlusAddressedEmail != value)
|
||||
|
@ -850,7 +853,7 @@ namespace Bit.App.Pages
|
|||
}
|
||||
}
|
||||
|
||||
await Device.InvokeOnMainThreadAsync(() => Page.DisplayAlert(AppResources.AnErrorHasOccurred, message, AppResources.Ok));
|
||||
await MainThread.InvokeOnMainThreadAsync(() => Page.DisplayAlert(AppResources.AnErrorHasOccurred, message, AppResources.Ok));
|
||||
}
|
||||
|
||||
private string GetUsernameTypeLabelDescription(UsernameType value)
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.Core.Resources.Localization;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
using Microsoft.Maui.ApplicationModel;
|
||||
using Bit.App.Utilities;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
|
@ -49,6 +44,8 @@ namespace Bit.App.Pages
|
|||
{
|
||||
get
|
||||
{
|
||||
if (_items == null) { return string.Empty; }
|
||||
|
||||
if (_items.TryGetValue(_selectedKey, out var option))
|
||||
{
|
||||
return option;
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Effects;
|
||||
using Bit.App.Effects;
|
||||
using Bit.App.Models;
|
||||
using Bit.Core.Resources.Localization;
|
||||
using Bit.App.Utilities;
|
||||
|
@ -8,8 +6,6 @@ using Bit.Core;
|
|||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
|
@ -60,8 +56,7 @@ namespace Bit.App.Pages
|
|||
};
|
||||
Children.Add(settingsPage);
|
||||
|
||||
// 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)
|
||||
{
|
||||
Effects.Add(new TabBarEffect());
|
||||
|
||||
|
@ -93,7 +88,7 @@ namespace Bit.App.Pages
|
|||
{
|
||||
if (message.Command == "syncCompleted")
|
||||
{
|
||||
Device.BeginInvokeOnMainThread(async () => await UpdateVaultButtonTitleAsync());
|
||||
MainThread.BeginInvokeOnMainThread(async () => await UpdateVaultButtonTitleAsync());
|
||||
}
|
||||
});
|
||||
await UpdateVaultButtonTitleAsync();
|
||||
|
@ -131,7 +126,7 @@ namespace Bit.App.Pages
|
|||
CurrentPage = _sendGroupingsPage;
|
||||
}
|
||||
|
||||
protected async override void OnCurrentPageChanged()
|
||||
protected override async void OnCurrentPageChanged()
|
||||
{
|
||||
if (CurrentPage is NavigationPage navPage)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue