1
0
mirror of https://github.com/bitwarden/mobile.git synced 2024-09-30 04:17:55 +02:00

PM-3349 Added Handler that enables the ExtendedDatePicker to get IsFocused events in Android. This is a workaround for fixing the current bug where it's not possible to select the "current day" in the expiration date of a Send.

Fix for TimePicker not displaying default Time Value
Updated some "Device" code to the new MAUI "DeviceInfo"
This commit is contained in:
Dinis Vieira 2023-11-02 02:32:12 +00:00
parent e90409d842
commit 946c465f0c
No known key found for this signature in database
GPG Key ID: 9389160FF6C295F3
12 changed files with 120 additions and 56 deletions

View File

@ -29,6 +29,7 @@
Bit.App.Handlers.ToolbarHandlerMappings.Setup(); Bit.App.Handlers.ToolbarHandlerMappings.Setup();
handlers.AddHandler(typeof(Bit.App.Pages.TabsPage), typeof(Bit.App.Handlers.CustomTabbedPageHandler)); handlers.AddHandler(typeof(Bit.App.Pages.TabsPage), typeof(Bit.App.Handlers.CustomTabbedPageHandler));
handlers.AddHandler(typeof(Bit.App.Controls.ExtendedDatePicker), typeof(Bit.App.Handlers.ExtendedDatePickerHandler));
#else #else
iOS.Core.Utilities.iOSCoreHelpers.ConfigureMAUIHandlers(handlers); iOS.Core.Utilities.iOSCoreHelpers.ConfigureMAUIHandlers(handlers);
#endif #endif

View File

@ -23,12 +23,12 @@ namespace Bit.App.Handlers
} }
}); });
DatePickerHandler.Mapper.AppendToMapping(nameof(IDatePicker.Date), UpdateTextPlaceholderOnFormatLikePlacholder); DatePickerHandler.Mapper.AppendToMapping(nameof(IDatePicker.Date), UpdateTextPlaceholderOnFormatLikePlaceholder);
DatePickerHandler.Mapper.AppendToMapping(nameof(IDatePicker.Format), UpdateTextPlaceholderOnFormatLikePlacholder); DatePickerHandler.Mapper.AppendToMapping(nameof(IDatePicker.Format), UpdateTextPlaceholderOnFormatLikePlaceholder);
} }
private static void UpdateTextPlaceholderOnFormatLikePlacholder(IDatePickerHandler handler, IDatePicker datePicker) private static void UpdateTextPlaceholderOnFormatLikePlaceholder(IDatePickerHandler handler, IDatePicker datePicker)
{ {
if (datePicker is ExtendedDatePicker extDatePicker && extDatePicker.Format == extDatePicker.PlaceHolder) if (datePicker is ExtendedDatePicker extDatePicker && extDatePicker.Format == extDatePicker.PlaceHolder)
{ {

View File

@ -0,0 +1,76 @@
using Android.App;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform;
namespace Bit.App.Handlers
{
// Note: This Handler exists only to allow the ExtendedDatePicker to receive IsFocused events on Android. iOS Already does this with this fix: https://github.com/dotnet/maui/pull/13321
// If MAUI eventually implements this behavior we can remove this handler completely. There is another Handler (DatePickerHandlerMappings) for the other DatePicker customizations.
public partial class ExtendedDatePickerHandler : DatePickerHandler
{
public static PropertyMapper<IDatePicker, ExtendedDatePickerHandler> PropertyMapper = new (DatePickerHandler.Mapper)
{
[nameof(IDatePicker.IsFocused)] = MapIsFocused
};
public ExtendedDatePickerHandler() : base(PropertyMapper)
{
}
public static void MapIsFocused(ExtendedDatePickerHandler handler, IDatePicker datePicker)
{
if (handler.PlatformView.IsFocused == datePicker.IsFocused) return;
if (datePicker.IsFocused)
{
handler.PlatformView.RequestFocus();
}
else
{
handler.PlatformView.ClearFocus();
}
}
private DatePickerDialog? _dialog;
protected override DatePickerDialog CreateDatePickerDialog(int year, int month, int day)
{
_dialog = base.CreateDatePickerDialog(year, month, day);
return _dialog;
}
protected override void ConnectHandler(MauiDatePicker platformView)
{
base.ConnectHandler(platformView);
if (_dialog != null)
{
_dialog.ShowEvent += OnDialogShown;
_dialog.DismissEvent += OnDialogDismissed;
}
}
//Currently the Disconnect Handler needs to be manually called from the App: https://github.com/dotnet/maui/issues/3604
protected override void DisconnectHandler(MauiDatePicker platformView)
{
if (_dialog != null)
{
_dialog.ShowEvent -= OnDialogShown;
_dialog.DismissEvent -= OnDialogDismissed;
}
base.DisconnectHandler(platformView);
_dialog = null;
}
private void OnDialogShown(object sender, EventArgs e)
{
this.VirtualView.IsFocused = true;
}
private void OnDialogDismissed(object sender, EventArgs e)
{
this.VirtualView.IsFocused = false;
}
}
}

View File

@ -16,19 +16,19 @@ namespace Bit.App.Handlers
handler.PlatformView.Gravity = GravityFlags.CenterHorizontal; handler.PlatformView.Gravity = GravityFlags.CenterHorizontal;
// use placeholder until NullableTime set // use placeholder until NullableTime set
if (!extTimePicker.NullableTime.HasValue) if (!extTimePicker.NullableTime.HasValue && !string.IsNullOrWhiteSpace(extTimePicker.PlaceHolder))
{ {
handler.PlatformView.Text = extTimePicker.PlaceHolder; handler.PlatformView.Text = extTimePicker.PlaceHolder;
} }
} }
}); });
TimePickerHandler.Mapper.AppendToMapping(nameof(ITimePicker.Time), UpdateTextPlaceholderOnFormatLikePlacholder); TimePickerHandler.Mapper.AppendToMapping(nameof(ITimePicker.Time), UpdateTextPlaceholderOnFormatLikePlaceholder);
TimePickerHandler.Mapper.AppendToMapping(nameof(ITimePicker.Format), UpdateTextPlaceholderOnFormatLikePlacholder); TimePickerHandler.Mapper.AppendToMapping(nameof(ITimePicker.Format), UpdateTextPlaceholderOnFormatLikePlaceholder);
} }
private static void UpdateTextPlaceholderOnFormatLikePlacholder(ITimePickerHandler handler, ITimePicker timePicker) private static void UpdateTextPlaceholderOnFormatLikePlaceholder(ITimePickerHandler handler, ITimePicker timePicker)
{ {
if (timePicker is ExtendedTimePicker extDatePicker && extDatePicker.Format == extDatePicker.PlaceHolder) if (timePicker is ExtendedTimePicker extDatePicker && extDatePicker.Format == extDatePicker.PlaceHolder)
{ {

View File

@ -4,6 +4,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:Bit.App.Controls" xmlns:controls="clr-namespace:Bit.App.Controls"
x:Class="Bit.App.Controls.DateTimePicker" x:Class="Bit.App.Controls.DateTimePicker"
Unloaded="DateTimePicker_OnUnloaded"
ColumnDefinitions="*,*"> ColumnDefinitions="*,*">
<controls:ExtendedDatePicker <controls:ExtendedDatePicker
x:Name="_datePicker" x:Name="_datePicker"

View File

@ -1,11 +1,4 @@
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using Microsoft.Maui.Controls;
using Microsoft.Maui;
using CommunityToolkit.Maui.Converters;
using CommunityToolkit.Maui.ImageSources;
using CommunityToolkit.Maui;
using CommunityToolkit.Maui.Core;
using CommunityToolkit.Maui.Layouts;
using CommunityToolkit.Maui.Views; using CommunityToolkit.Maui.Views;
namespace Bit.App.Controls namespace Bit.App.Controls
@ -32,6 +25,11 @@ namespace Bit.App.Controls
_timePicker.PlaceHolder = dateTimeViewModel.TimePlaceholder; _timePicker.PlaceHolder = dateTimeViewModel.TimePlaceholder;
} }
} }
private void DateTimePicker_OnUnloaded(object sender, EventArgs e)
{
_datePicker?.DisconnectHandler();
}
} }
public class LazyDateTimePicker : LazyView<DateTimePicker> public class LazyDateTimePicker : LazyView<DateTimePicker>

View File

@ -1,5 +1,4 @@
using System; using Bit.Core.Utilities;
using Bit.Core.Utilities;
namespace Bit.App.Controls namespace Bit.App.Controls
{ {

View File

@ -1,8 +1,4 @@
using System; namespace Bit.App.Controls
using Microsoft.Maui.Controls;
using Microsoft.Maui;
namespace Bit.App.Controls
{ {
public class ExtendedDatePicker : DatePicker public class ExtendedDatePicker : DatePicker
{ {
@ -83,5 +79,11 @@ namespace Bit.App.Controls
} }
} }
} }
//Currently the Disconnect Handler needs to be manually called from the App: https://github.com/dotnet/maui/issues/3604
public void DisconnectHandler()
{
Handler?.DisconnectHandler();
}
} }
} }

View File

@ -1,8 +1,4 @@
using System; namespace Bit.App.Controls
using Microsoft.Maui.Controls;
using Microsoft.Maui;
namespace Bit.App.Controls
{ {
public class ExtendedTimePicker : TimePicker public class ExtendedTimePicker : TimePicker
{ {

View File

@ -12,6 +12,7 @@
xmlns:core="clr-namespace:Bit.Core" xmlns:core="clr-namespace:Bit.Core"
x:DataType="pages:SendAddEditPageViewModel" x:DataType="pages:SendAddEditPageViewModel"
HideSoftInputOnTapped="True" HideSoftInputOnTapped="True"
Unloaded="OnUnloaded"
x:Name="_page" x:Name="_page"
Title="{Binding PageTitle}"> Title="{Binding PageTitle}">
<ContentPage.BindingContext> <ContentPage.BindingContext>
@ -310,6 +311,7 @@
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<controls:ExtendedDatePicker <controls:ExtendedDatePicker
x:Name="_deletionExtendedDatePicker"
NullableDate="{Binding DeletionDateTimeViewModel.Date, Mode=TwoWay}" NullableDate="{Binding DeletionDateTimeViewModel.Date, Mode=TwoWay}"
Format="d" Format="d"
IsEnabled="{Binding SendEnabled}" IsEnabled="{Binding SendEnabled}"
@ -353,6 +355,7 @@
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<controls:ExtendedDatePicker <controls:ExtendedDatePicker
x:Name="_expirationExtendedDatePicker"
NullableDate="{Binding ExpirationDateTimeViewModel.Date, Mode=TwoWay}" NullableDate="{Binding ExpirationDateTimeViewModel.Date, Mode=TwoWay}"
PlaceHolder="mm/dd/yyyy" PlaceHolder="mm/dd/yyyy"
Format="d" Format="d"

View File

@ -1,7 +1,4 @@
using System; using Bit.App.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
using Bit.App.Models;
using Bit.Core.Resources.Localization; using Bit.Core.Resources.Localization;
using Bit.App.Utilities; using Bit.App.Utilities;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
@ -9,8 +6,6 @@ using Bit.Core.Enums;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Microsoft.Maui.Controls.PlatformConfiguration; using Microsoft.Maui.Controls.PlatformConfiguration;
using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific; using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific;
using Microsoft.Maui.Controls;
using Microsoft.Maui;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@ -39,8 +34,7 @@ namespace Bit.App.Pages
_vm.SendId = sendId; _vm.SendId = sendId;
_vm.Type = appOptions?.CreateSend?.Item1 ?? type; _vm.Type = appOptions?.CreateSend?.Item1 ?? type;
SetActivityIndicator(); SetActivityIndicator();
// 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 (DeviceInfo.Platform == DevicePlatform.Android)
if (Device.RuntimePlatform == Device.Android)
{ {
if (_vm.EditMode) if (_vm.EditMode)
{ {
@ -57,7 +51,7 @@ namespace Bit.App.Pages
_btnOptionsDown.WidthRequest = 30; _btnOptionsDown.WidthRequest = 30;
_btnOptionsUp.WidthRequest = 30; _btnOptionsUp.WidthRequest = 30;
} }
else if (Device.RuntimePlatform == Device.iOS) else if (DeviceInfo.Platform == DevicePlatform.iOS)
{ {
ToolbarItems.Add(_closeItem); ToolbarItems.Add(_closeItem);
if (_vm.EditMode) if (_vm.EditMode)
@ -102,7 +96,7 @@ namespace Bit.App.Pages
{ {
if (message.Command == "selectFileResult") if (message.Command == "selectFileResult")
{ {
Device.BeginInvokeOnMainThread(() => MainThread.BeginInvokeOnMainThread(() =>
{ {
var data = message.Data as Tuple<byte[], string>; var data = message.Data as Tuple<byte[], string>;
_vm.FileData = data.Item1; _vm.FileData = data.Item1;
@ -141,8 +135,7 @@ namespace Bit.App.Pages
protected override bool OnBackButtonPressed() protected override bool OnBackButtonPressed()
{ {
// 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 (_vm.IsAddFromShare && DeviceInfo.Platform == DevicePlatform.Android)
if (_vm.IsAddFromShare && Device.RuntimePlatform == Device.Android)
{ {
_appOptions.CreateSend = null; _appOptions.CreateSend = null;
} }
@ -152,13 +145,18 @@ namespace Bit.App.Pages
protected override void OnDisappearing() protected override void OnDisappearing()
{ {
base.OnDisappearing(); base.OnDisappearing();
// 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 (DeviceInfo.Platform == DevicePlatform.iOS)
if (Device.RuntimePlatform != Device.iOS)
{ {
_broadcasterService.Unsubscribe(nameof(SendAddEditPage)); _broadcasterService.Unsubscribe(nameof(SendAddEditPage));
} }
} }
private void OnUnloaded(object sender, EventArgs e)
{
_deletionExtendedDatePicker?.DisconnectHandler();
_expirationExtendedDatePicker?.DisconnectHandler();
}
private async void TextType_Clicked(object sender, EventArgs eventArgs) private async void TextType_Clicked(object sender, EventArgs eventArgs)
{ {
await _vm.TypeChangedAsync(SendType.Text); await _vm.TypeChangedAsync(SendType.Text);
@ -310,8 +308,7 @@ namespace Bit.App.Pages
private void AdjustToolbar() private void AdjustToolbar()
{ {
_saveItem.IsEnabled = _vm.SendEnabled; _saveItem.IsEnabled = _vm.SendEnabled;
// 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 (!_vm.SendEnabled && _vm.EditMode && DeviceInfo.Platform == DevicePlatform.Android)
if (!_vm.SendEnabled && _vm.EditMode && Device.RuntimePlatform == Device.Android)
{ {
ToolbarItems.Remove(_removePassword); ToolbarItems.Remove(_removePassword);
ToolbarItems.Remove(_copyLink); ToolbarItems.Remove(_copyLink);

View File

@ -1,7 +1,4 @@
using System; using Bit.App.Abstractions;
using System.Collections.Generic;
using System.Threading.Tasks;
using Bit.App.Abstractions;
using Bit.App.Controls; using Bit.App.Controls;
using Bit.Core.Resources.Localization; using Bit.Core.Resources.Localization;
using Bit.App.Utilities; using Bit.App.Utilities;
@ -11,9 +8,6 @@ using Bit.Core.Enums;
using Bit.Core.Exceptions; using Bit.Core.Exceptions;
using Bit.Core.Models.View; using Bit.Core.Models.View;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Microsoft.Maui.Networking;
using Microsoft.Maui.Controls;
using Microsoft.Maui;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@ -395,8 +389,7 @@ namespace Bit.App.Pages
var sendId = await _sendService.SaveWithServerAsync(send, encryptedFileData); var sendId = await _sendService.SaveWithServerAsync(send, encryptedFileData);
await _deviceActionService.HideLoadingAsync(); await _deviceActionService.HideLoadingAsync();
// 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 (DeviceInfo.Platform == DevicePlatform.Android && IsFile)
if (Device.RuntimePlatform == Device.Android && IsFile)
{ {
// Workaround for https://github.com/xamarin/Xamarin.Forms/issues/5418 // Workaround for https://github.com/xamarin/Xamarin.Forms/issues/5418
// Exiting and returning (file picker) calls OnAppearing on list page instead of this modal, and // Exiting and returning (file picker) calls OnAppearing on list page instead of this modal, and
@ -455,8 +448,7 @@ namespace Bit.App.Pages
{ {
if (IsAddFromShare) if (IsAddFromShare)
{ {
// 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 (DeviceInfo.Platform == DevicePlatform.Android)
if (Device.RuntimePlatform == Device.Android)
{ {
_deviceActionService.CloseMainApp(); _deviceActionService.CloseMainApp();
return; return;
@ -513,8 +505,7 @@ namespace Bit.App.Pages
await _platformUtilsService.ShowDialogAsync(AppResources.SendFileEmailVerificationRequired); await _platformUtilsService.ShowDialogAsync(AppResources.SendFileEmailVerificationRequired);
} }
// 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 (IsAddFromShare && DeviceInfo.Platform == DevicePlatform.Android)
if (IsAddFromShare && Device.RuntimePlatform == Device.Android)
{ {
_deviceActionService.CloseMainApp(); _deviceActionService.CloseMainApp();
return; return;
@ -630,7 +621,7 @@ namespace Bit.App.Pages
internal void TriggerSendTextPropertyChanged() internal void TriggerSendTextPropertyChanged()
{ {
Device.BeginInvokeOnMainThread(() => TriggerPropertyChanged(nameof(Send))); MainThread.BeginInvokeOnMainThread(() => TriggerPropertyChanged(nameof(Send)));
} }
} }
} }