diff --git a/src/Maui/Bitwarden/Bitwarden.csproj b/src/Maui/Bitwarden/Bitwarden.csproj
index 9b6ecb85f..3f4fde0cf 100644
--- a/src/Maui/Bitwarden/Bitwarden.csproj
+++ b/src/Maui/Bitwarden/Bitwarden.csproj
@@ -45,10 +45,8 @@
-
-
-
+
@@ -302,6 +300,10 @@
+
+
+
+
@@ -313,6 +315,7 @@
+
diff --git a/src/Maui/Bitwarden/Controls/IconButton.cs b/src/Maui/Bitwarden/Controls/IconButton.cs
index d27d50626..faa4ab8ed 100644
--- a/src/Maui/Bitwarden/Controls/IconButton.cs
+++ b/src/Maui/Bitwarden/Controls/IconButton.cs
@@ -16,7 +16,7 @@ namespace Bit.App.Controls
FontFamily = "bwi-font";
break;
case Device.Android:
- FontFamily = "bwi-font.ttf#bwi-font";
+ FontFamily = "bwi-font";
break;
}
diff --git a/src/Maui/Bitwarden/Controls/IconLabel.cs b/src/Maui/Bitwarden/Controls/IconLabel.cs
index 6b5e72308..3df6881ec 100644
--- a/src/Maui/Bitwarden/Controls/IconLabel.cs
+++ b/src/Maui/Bitwarden/Controls/IconLabel.cs
@@ -17,7 +17,7 @@ namespace Bit.App.Controls
FontFamily = "bwi-font";
break;
case Device.Android:
- FontFamily = "bwi-font.ttf#bwi-font";
+ FontFamily = "bwi-font";
break;
}
diff --git a/src/Maui/Bitwarden/Controls/MiButton.cs b/src/Maui/Bitwarden/Controls/MiButton.cs
index 99309351b..a181ab177 100644
--- a/src/Maui/Bitwarden/Controls/MiButton.cs
+++ b/src/Maui/Bitwarden/Controls/MiButton.cs
@@ -15,7 +15,7 @@ namespace Bit.App.Controls
FontFamily = "Material Icons";
break;
case Device.Android:
- FontFamily = "MaterialIcons_Regular.ttf#Material Icons";
+ FontFamily = "MaterialIcons_Regular";
break;
}
}
diff --git a/src/Maui/Bitwarden/Controls/MiLabel.cs b/src/Maui/Bitwarden/Controls/MiLabel.cs
index 4d510899f..603a3a738 100644
--- a/src/Maui/Bitwarden/Controls/MiLabel.cs
+++ b/src/Maui/Bitwarden/Controls/MiLabel.cs
@@ -14,7 +14,7 @@ namespace Bit.App.Controls
FontFamily = "Material Icons";
break;
case Device.Android:
- FontFamily = "MaterialIcons_Regular.ttf#Material Icons";
+ FontFamily = "MaterialIcons_Regular";
break;
}
}
diff --git a/src/Maui/Bitwarden/Controls/MonoEntry.cs b/src/Maui/Bitwarden/Controls/MonoEntry.cs
index dfa85d849..9bbff5bce 100644
--- a/src/Maui/Bitwarden/Controls/MonoEntry.cs
+++ b/src/Maui/Bitwarden/Controls/MonoEntry.cs
@@ -7,16 +7,11 @@ namespace Bit.App.Controls
{
public MonoEntry()
{
- // 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
- switch (Device.RuntimePlatform)
- {
- case Device.iOS:
- FontFamily = "Menlo-Regular";
- break;
- case Device.Android:
- FontFamily = "RobotoMono_Regular.ttf#Roboto Mono";
- break;
- }
+#if ANDROID
+ FontFamily = "RobotoMono_Regular";
+#elif IOS
+ FontFamily = "Menlo-Regular";
+#endif
}
}
}
diff --git a/src/Maui/Bitwarden/Controls/MonoLabel.cs b/src/Maui/Bitwarden/Controls/MonoLabel.cs
index 6baaf399e..b4da3f7a5 100644
--- a/src/Maui/Bitwarden/Controls/MonoLabel.cs
+++ b/src/Maui/Bitwarden/Controls/MonoLabel.cs
@@ -14,7 +14,7 @@ namespace Bit.App.Controls
FontFamily = "Menlo-Regular";
break;
case Device.Android:
- FontFamily = "RobotoMono_Regular.ttf#Roboto Mono";
+ FontFamily = "RobotoMono_Regular";
break;
}
}
diff --git a/src/Maui/Bitwarden/Effects/FabShadowEffect.cs b/src/Maui/Bitwarden/Effects/FabShadowEffect.cs
index 2cdd37a02..58806646d 100644
--- a/src/Maui/Bitwarden/Effects/FabShadowEffect.cs
+++ b/src/Maui/Bitwarden/Effects/FabShadowEffect.cs
@@ -1,12 +1,38 @@
using Microsoft.Maui.Controls;
using Microsoft.Maui;
+using Microsoft.Maui.Controls.Platform;
+
+#if ANDROID
+using Android.Graphics.Drawables;
+using Bit.App.Droid.Utilities;
+#endif
namespace Bit.App.Effects
{
public class FabShadowEffect : RoutingEffect
{
- public FabShadowEffect()
- : base("Bitwarden.FabShadowEffect")
- { }
}
+
+#if ANDROID
+ public class FabShadowPlatformEffect : PlatformEffect
+ {
+ protected override void OnAttached()
+ {
+ if (Control is Android.Widget.Button button)
+ {
+ var gd = new GradientDrawable();
+ gd.SetColor(ThemeHelpers.FabColor);
+ gd.SetCornerRadius(100);
+
+ button.SetBackground(gd);
+ button.Elevation = 6;
+ button.TranslationZ = 20;
+ }
+ }
+
+ protected override void OnDetached()
+ {
+ }
+ }
+#endif
}
diff --git a/src/Maui/Bitwarden/Effects/FixedSizeEffect.cs b/src/Maui/Bitwarden/Effects/FixedSizeEffect.cs
index 471151cab..7cfb83e97 100644
--- a/src/Maui/Bitwarden/Effects/FixedSizeEffect.cs
+++ b/src/Maui/Bitwarden/Effects/FixedSizeEffect.cs
@@ -1,12 +1,32 @@
using Microsoft.Maui.Controls;
using Microsoft.Maui;
+using Microsoft.Maui.Controls.Platform;
+
+#if ANDROID
+using Android.Widget;
+#endif
+
namespace Bit.App.Effects
{
public class FixedSizeEffect : RoutingEffect
{
- public FixedSizeEffect()
- : base("Bitwarden.FixedSizeEffect")
- { }
}
+
+#if ANDROID
+ public class FixedSizePlatformEffect : PlatformEffect
+ {
+ protected override void OnAttached()
+ {
+ if (Element is Label label && Control is TextView textView)
+ {
+ textView.SetTextSize(Android.Util.ComplexUnitType.Pt, (float)label.FontSize);
+ }
+ }
+
+ protected override void OnDetached()
+ {
+ }
+ }
+#endif
}
diff --git a/src/Maui/Bitwarden/Effects/NoEmojiKeyboardEffect.cs b/src/Maui/Bitwarden/Effects/NoEmojiKeyboardEffect.cs
index b8830441b..4e0b60bdd 100644
--- a/src/Maui/Bitwarden/Effects/NoEmojiKeyboardEffect.cs
+++ b/src/Maui/Bitwarden/Effects/NoEmojiKeyboardEffect.cs
@@ -1,13 +1,32 @@
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui;
+using Microsoft.Maui.Controls.Platform;
+
+#if ANDROID
+using Android.Widget;
+#endif
namespace Bit.App.Effects
{
public class NoEmojiKeyboardEffect : RoutingEffect
{
- public NoEmojiKeyboardEffect()
- : base("Bitwarden.NoEmojiKeyboardEffect")
- { }
}
+
+#if ANDROID
+ public class NoEmojiKeyboardPlatformEffect : PlatformEffect
+ {
+ protected override void OnAttached()
+ {
+ if (Control is EditText editText)
+ {
+ editText.InputType = Android.Text.InputTypes.ClassText | Android.Text.InputTypes.TextVariationVisiblePassword | Android.Text.InputTypes.TextFlagMultiLine;
+ }
+ }
+
+ protected override void OnDetached()
+ {
+ }
+ }
+#endif
}
diff --git a/src/Maui/Bitwarden/Effects/RemoveFontPaddingEffect.cs b/src/Maui/Bitwarden/Effects/RemoveFontPaddingEffect.cs
index 0e5eb29ba..885b5f057 100644
--- a/src/Maui/Bitwarden/Effects/RemoveFontPaddingEffect.cs
+++ b/src/Maui/Bitwarden/Effects/RemoveFontPaddingEffect.cs
@@ -1,14 +1,32 @@
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui;
+using Microsoft.Maui.Controls.Platform;
+#if ANDROID
+using Android.Widget;
+#endif
namespace Bit.App.Effects
{
public class RemoveFontPaddingEffect : RoutingEffect
{
- public RemoveFontPaddingEffect()
- : base("Bitwarden.RemoveFontPaddingEffect")
- { }
}
+
+#if ANDROID
+ public class RemoveFontPaddingPlatformEffect : PlatformEffect
+ {
+ protected override void OnAttached()
+ {
+ if (Control is TextView textView)
+ {
+ textView.SetIncludeFontPadding(false);
+ }
+ }
+
+ protected override void OnDetached()
+ {
+ }
+ }
+#endif
}
diff --git a/src/Maui/Bitwarden/Effects/TabBarEffect.cs b/src/Maui/Bitwarden/Effects/TabBarEffect.cs
index 8e6c46544..41998e844 100644
--- a/src/Maui/Bitwarden/Effects/TabBarEffect.cs
+++ b/src/Maui/Bitwarden/Effects/TabBarEffect.cs
@@ -1,12 +1,34 @@
using Microsoft.Maui.Controls;
using Microsoft.Maui;
+using Microsoft.Maui.Controls.Platform;
namespace Bit.App.Effects
{
public class TabBarEffect : RoutingEffect
{
- public TabBarEffect()
- : base("Bitwarden.TabBarEffect")
- { }
}
+
+#if ANDROID
+ public class TabBarPlatformEffect : PlatformEffect
+ {
+ protected override void OnAttached()
+ {
+ // TODO: [MAUI-Migration] [Critical]
+ // now Container is View instead of ViewGroup, let's review this
+ //if (!(Container.GetChildAt(0) is ViewGroup layout))
+ //{
+ // return;
+ //}
+ //if (!(layout.GetChildAt(1) is BottomNavigationView bottomNavigationView))
+ //{
+ // return;
+ //}
+ //bottomNavigationView.LabelVisibilityMode = LabelVisibilityMode.LabelVisibilityLabeled;
+ }
+
+ protected override void OnDetached()
+ {
+ }
+ }
+#endif
}
diff --git a/src/Maui/Bitwarden/MauiProgram.cs b/src/Maui/Bitwarden/MauiProgram.cs
index 8f968c057..64035cb30 100644
--- a/src/Maui/Bitwarden/MauiProgram.cs
+++ b/src/Maui/Bitwarden/MauiProgram.cs
@@ -1,4 +1,5 @@
using System;
+using Bit.App.Controls;
using CommunityToolkit.Maui;
using FFImageLoading.Maui;
using Microsoft.Extensions.Logging;
@@ -13,7 +14,7 @@ namespace Bit.App;
public static class MauiProgram
{
- public static MauiApp CreateMauiApp(Action effectsBuilder)
+ public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
@@ -23,12 +24,47 @@ public static class MauiProgram
.UseBarcodeReader()
.UseSkiaSharp()
.UseFFImageLoading()
- .ConfigureEffects(effectsBuilder)
+ .ConfigureEffects(effects =>
+ {
+#if ANDROID
+ effects.Add();
+ effects.Add();
+ effects.Add();
+ effects.Add();
+ effects.Add();
+#endif
+ })
.ConfigureFonts(fonts =>
{
- fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
- fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
+ fonts.AddFont("RobotoMono_Regular.ttf#Roboto Mono", "RobotoMono_Regular");
+ fonts.AddFont("bwi-font.ttf#bwi-font", "bwi-font");
+ fonts.AddFont("MaterialIcons_Regular.ttf#Material Icons", "MaterialIcons_Regular");
});
+ // TODO: [MAUI-Migration] Convert renderers to handlers
+ // Currently, there's an issue on reusing renderers https://github.com/dotnet/maui/issues/9936
+// .ConfigureMauiHandlers(handlers =>
+// {
+//#if ANDROID
+// handlers.AddHandler(typeof(Editor), typeof(Droid.Renderers.CustomEditorRenderer));
+// handlers.AddHandler(typeof(Entry), typeof(Droid.Renderers.CustomEntryRenderer));
+// handlers.AddHandler(typeof(CustomLabel), typeof(Droid.Renderers.CustomLabelRenderer));
+// //handlers.AddHandler(typeof(ContentPage), typeof(Droid.Renderers.CustomPageRenderer));
+// handlers.AddHandler(typeof(Picker), typeof(Droid.Renderers.CustomPickerRenderer));
+// handlers.AddHandler(typeof(SearchBar), typeof(Droid.Renderers.CustomSearchBarRenderer));
+// handlers.AddHandler(typeof(Switch), typeof(Droid.Renderers.CustomSwitchRenderer));
+// handlers.AddHandler(typeof(TabbedPage), typeof(Droid.Renderers.CustomTabbedRenderer));
+// handlers.AddHandler(typeof(ExtendedDatePicker), typeof(Droid.Renderers.ExtendedDatePickerRenderer));
+// handlers.AddHandler(typeof(ExtendedGrid), typeof(Droid.Renderers.ExtendedGridRenderer));
+// handlers.AddHandler(typeof(ExtendedSlider), typeof(Droid.Renderers.ExtendedSliderRenderer));
+// handlers.AddHandler(typeof(ExtendedStackLayout), typeof(Droid.Renderers.ExtendedStackLayoutRenderer));
+// handlers.AddHandler(typeof(ExtendedStepper), typeof(Droid.Renderers.ExtendedStepperRenderer));
+// handlers.AddHandler(typeof(ExtendedTimePicker), typeof(Droid.Renderers.ExtendedTimePickerRenderer));
+// handlers.AddHandler(typeof(HybridWebView), typeof(Droid.Renderers.HybridWebViewRenderer));
+// handlers.AddHandler(typeof(SelectableLabel), typeof(Droid.Renderers.SelectableLabelRenderer));
+//#elif IOS
+// // TODO: configure
+//#endif
+// });
#if DEBUG
builder.Logging.AddDebug();
diff --git a/src/Maui/Bitwarden/Pages/Vault/CipherDetailsPageViewModel.cs b/src/Maui/Bitwarden/Pages/Vault/CipherDetailsPageViewModel.cs
index 87d54c076..31cbf19c8 100644
--- a/src/Maui/Bitwarden/Pages/Vault/CipherDetailsPageViewModel.cs
+++ b/src/Maui/Bitwarden/Pages/Vault/CipherDetailsPageViewModel.cs
@@ -199,11 +199,14 @@ namespace Bit.App.Pages
Text = string.Format("{0}:", AppResources.PasswordHistory),
FontAttributes = FontAttributes.Bold
});
- fs.Spans.Add(new Span
+ if (Cipher?.PasswordHistory != null)
{
- Text = string.Format(" {0}", Cipher.PasswordHistory.Count.ToString()),
- TextColor = ThemeManager.GetResourceColor("PrimaryColor")
- });
+ fs.Spans.Add(new Span
+ {
+ Text = string.Format(" {0}", Cipher.PasswordHistory.Count.ToString()),
+ TextColor = ThemeManager.GetResourceColor("PrimaryColor")
+ });
+ }
return fs;
}
}
diff --git a/src/Maui/Bitwarden/Pages/Vault/GroupingsPage/GroupingsPage.xaml.cs b/src/Maui/Bitwarden/Pages/Vault/GroupingsPage/GroupingsPage.xaml.cs
index e2fb773b9..263a8e71f 100644
--- a/src/Maui/Bitwarden/Pages/Vault/GroupingsPage/GroupingsPage.xaml.cs
+++ b/src/Maui/Bitwarden/Pages/Vault/GroupingsPage/GroupingsPage.xaml.cs
@@ -90,7 +90,7 @@ namespace Bit.App.Pages
base.OnAppearing();
if (_syncService.SyncInProgress)
{
- IsBusy = true;
+ MainThread.BeginInvokeOnMainThread(() => IsBusy = true);
}
_accountAvatar?.OnAppearing();
@@ -105,7 +105,7 @@ namespace Bit.App.Pages
{
if (message.Command == "syncStarted")
{
- Device.BeginInvokeOnMainThread(() => IsBusy = true);
+ MainThread.BeginInvokeOnMainThread(() => IsBusy = true);
}
else if (message.Command == "syncCompleted")
{
@@ -114,7 +114,7 @@ namespace Bit.App.Pages
{
_vm.AvatarImageSource = await GetAvatarImageSourceAsync();
}
- Device.BeginInvokeOnMainThread(() =>
+ MainThread.BeginInvokeOnMainThread(() =>
{
IsBusy = false;
if (_vm.LoadedOnce)
diff --git a/src/Maui/Bitwarden/Platforms/Android/Effects/FabShadowEffect.cs b/src/Maui/Bitwarden/Platforms/Android/Effects/FabShadowEffect.cs
deleted file mode 100644
index 0b89e06be..000000000
--- a/src/Maui/Bitwarden/Platforms/Android/Effects/FabShadowEffect.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using Android.Graphics.Drawables;
-using Bit.App.Droid.Effects;
-using Bit.App.Droid.Utilities;
-using Microsoft.Maui.Controls.Platform;
-
-[assembly: ExportEffect(typeof(FabShadowEffect), "FabShadowEffect")]
-namespace Bit.App.Droid.Effects
-{
- public class FabShadowEffect : PlatformEffect
- {
- protected override void OnAttached ()
- {
- if (Control is Android.Widget.Button button)
- {
- var gd = new GradientDrawable();
- gd.SetColor(ThemeHelpers.FabColor);
- gd.SetCornerRadius(100);
-
- button.SetBackground(gd);
- button.Elevation = 6;
- button.TranslationZ = 20;
- }
- }
-
- protected override void OnDetached ()
- {
- }
- }
-}
diff --git a/src/Maui/Bitwarden/Platforms/Android/Effects/FixedSizeEffect.cs b/src/Maui/Bitwarden/Platforms/Android/Effects/FixedSizeEffect.cs
deleted file mode 100644
index e18ea1ae8..000000000
--- a/src/Maui/Bitwarden/Platforms/Android/Effects/FixedSizeEffect.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Android.Widget;
-using Bit.App.Droid.Effects;
-using Microsoft.Maui.Controls.Platform;
-
-[assembly: ExportEffect(typeof(FixedSizeEffect), "FixedSizeEffect")]
-namespace Bit.App.Droid.Effects
-{
- public class FixedSizeEffect : PlatformEffect
- {
- protected override void OnAttached()
- {
- if (Element is Label label && Control is TextView textView)
- {
- textView.SetTextSize(Android.Util.ComplexUnitType.Pt, (float)label.FontSize);
- }
- }
-
- protected override void OnDetached()
- {
- }
- }
-}
diff --git a/src/Maui/Bitwarden/Platforms/Android/Effects/NoEmojiKeyboardEffect.cs b/src/Maui/Bitwarden/Platforms/Android/Effects/NoEmojiKeyboardEffect.cs
deleted file mode 100644
index 9eaa6833a..000000000
--- a/src/Maui/Bitwarden/Platforms/Android/Effects/NoEmojiKeyboardEffect.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using Android.Widget;
-using Bit.App.Droid.Effects;
-using Microsoft.Maui.Controls.Platform;
-
-[assembly: ExportEffect(typeof(NoEmojiKeyboardEffect), nameof(NoEmojiKeyboardEffect))]
-namespace Bit.App.Droid.Effects
-{
- public class NoEmojiKeyboardEffect : PlatformEffect
- {
- protected override void OnAttached()
- {
- if (Control is EditText editText)
- {
- editText.InputType = Android.Text.InputTypes.ClassText | Android.Text.InputTypes.TextVariationVisiblePassword | Android.Text.InputTypes.TextFlagMultiLine;
- }
- }
-
- protected override void OnDetached()
- {
- }
- }
-}
-
diff --git a/src/Maui/Bitwarden/Platforms/Android/Effects/RemoveFontPaddingEffect.cs b/src/Maui/Bitwarden/Platforms/Android/Effects/RemoveFontPaddingEffect.cs
deleted file mode 100644
index 97e03cd11..000000000
--- a/src/Maui/Bitwarden/Platforms/Android/Effects/RemoveFontPaddingEffect.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Android.Widget;
-using Bit.App.Droid.Effects;
-using Microsoft.Maui.Controls.Platform;
-
-[assembly: ExportEffect(typeof(RemoveFontPaddingEffect), nameof(RemoveFontPaddingEffect))]
-namespace Bit.App.Droid.Effects
-{
- public class RemoveFontPaddingEffect : PlatformEffect
- {
- protected override void OnAttached()
- {
- if (Control is TextView textView)
- {
- textView.SetIncludeFontPadding(false);
- }
- }
-
- protected override void OnDetached()
- {
- }
- }
-}
\ No newline at end of file
diff --git a/src/Maui/Bitwarden/Platforms/Android/Effects/TabBarEffect.cs b/src/Maui/Bitwarden/Platforms/Android/Effects/TabBarEffect.cs
deleted file mode 100644
index 2ef4c4aa9..000000000
--- a/src/Maui/Bitwarden/Platforms/Android/Effects/TabBarEffect.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using Android.Views;
-using Bit.App.Droid.Effects;
-using Google.Android.Material.BottomNavigation;
-using Microsoft.Maui.Controls;
-using Microsoft.Maui.Controls.Platform;
-
-[assembly: ResolutionGroupName("Bitwarden")]
-[assembly: ExportEffect(typeof(TabBarEffect), "TabBarEffect")]
-namespace Bit.App.Droid.Effects
-{
- public class TabBarEffect : PlatformEffect
- {
- protected override void OnAttached()
- {
- // TODO: [MAUI-Migration] [Critical]
- // now Container is View instead of ViewGroup, let's review this
- //if (!(Container.GetChildAt(0) is ViewGroup layout))
- //{
- // return;
- //}
- //if (!(layout.GetChildAt(1) is BottomNavigationView bottomNavigationView))
- //{
- // return;
- //}
- //bottomNavigationView.LabelVisibilityMode = LabelVisibilityMode.LabelVisibilityLabeled;
- }
-
- protected override void OnDetached()
- {
- }
- }
-}
diff --git a/src/Maui/Bitwarden/Platforms/Android/MainApplication.cs b/src/Maui/Bitwarden/Platforms/Android/MainApplication.cs
index ef2964c34..810e3e622 100644
--- a/src/Maui/Bitwarden/Platforms/Android/MainApplication.cs
+++ b/src/Maui/Bitwarden/Platforms/Android/MainApplication.cs
@@ -98,16 +98,7 @@ namespace Bit.App.Droid
#endif
}
- protected override MauiApp CreateMauiApp()
- {
- return MauiProgram.CreateMauiApp(effects =>
- {
- effects.Add();
- effects.Add();
- effects.Add();
- effects.Add();
- });
- }
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
public override void OnCreate()
{
diff --git a/src/Maui/Bitwarden/Platforms/Android/Renderers/CustomEditorRenderer.cs b/src/Maui/Bitwarden/Platforms/Android/Renderers/CustomEditorRenderer.cs
new file mode 100644
index 000000000..8c69acced
--- /dev/null
+++ b/src/Maui/Bitwarden/Platforms/Android/Renderers/CustomEditorRenderer.cs
@@ -0,0 +1,67 @@
+using System.ComponentModel;
+using Android.Content;
+using Android.Content.Res;
+using Android.Views.InputMethods;
+using Bit.App.Droid.Utilities;
+using Microsoft.Maui.Controls.Compatibility.Platform.Android;
+using Microsoft.Maui.Controls.Platform;
+
+namespace Bit.App.Droid.Renderers
+{
+ public class CustomEditorRenderer : EditorRenderer
+ {
+ public CustomEditorRenderer(Context context)
+ : base(context)
+ { }
+
+ // Workaround for issue described here:
+ // https://github.com/xamarin/Xamarin.Forms/issues/8291#issuecomment-617456651
+ protected override void OnAttachedToWindow()
+ {
+ base.OnAttachedToWindow();
+ EditText.Enabled = false;
+ EditText.Enabled = true;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs e)
+ {
+ base.OnElementChanged(e);
+ UpdateBorderColor();
+ if (Control != null && e.NewElement != null)
+ {
+ Control.SetPadding(Control.PaddingLeft, Control.PaddingTop - 10, Control.PaddingRight,
+ Control.PaddingBottom + 20);
+ Control.ImeOptions = Control.ImeOptions | (ImeAction)ImeFlags.NoPersonalizedLearning |
+ (ImeAction)ImeFlags.NoExtractUi;
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Entry.TextColorProperty.PropertyName)
+ {
+ UpdateBorderColor();
+ }
+ }
+
+ private void UpdateBorderColor()
+ {
+ if (Control != null)
+ {
+ var states = new[]
+ {
+ new[] { Android.Resource.Attribute.StateFocused }, // focused
+ new[] { -Android.Resource.Attribute.StateFocused }, // unfocused
+ };
+ var colors = new int[]
+ {
+ ThemeHelpers.PrimaryColor,
+ ThemeHelpers.MutedColor
+ };
+ Control.BackgroundTintList = new ColorStateList(states, colors);
+ }
+ }
+ }
+}
diff --git a/src/Maui/Bitwarden/Platforms/Android/Renderers/CustomEntryRenderer.cs b/src/Maui/Bitwarden/Platforms/Android/Renderers/CustomEntryRenderer.cs
new file mode 100644
index 000000000..e68c8e3af
--- /dev/null
+++ b/src/Maui/Bitwarden/Platforms/Android/Renderers/CustomEntryRenderer.cs
@@ -0,0 +1,106 @@
+using System.ComponentModel;
+using Android.Content;
+using Android.Content.Res;
+using Android.Graphics;
+using Android.Text;
+using Android.Views.InputMethods;
+using Android.Widget;
+using Bit.App.Droid.Utilities;
+using Microsoft.Maui.Controls.Compatibility.Platform.Android;
+using Microsoft.Maui.Controls.Platform;
+using Microsoft.Maui.Platform;
+
+namespace Bit.App.Droid.Renderers
+{
+ public class CustomEntryRenderer : EntryRenderer
+ {
+ public CustomEntryRenderer(Context context)
+ : base(context)
+ { }
+
+ protected override void OnElementChanged(ElementChangedEventArgs e)
+ {
+ base.OnElementChanged(e);
+ UpdateBorderColor();
+ if (Control != null && e.NewElement != null)
+ {
+ Control.SetPadding(Control.PaddingLeft, Control.PaddingTop - 10, Control.PaddingRight,
+ Control.PaddingBottom + 20);
+ Control.ImeOptions = Control.ImeOptions | (ImeAction)ImeFlags.NoPersonalizedLearning |
+ (ImeAction)ImeFlags.NoExtractUi;
+ }
+ }
+
+ // Workaround for bug preventing long-press -> copy/paste on Android 11
+ // See https://issuetracker.google.com/issues/37095917
+ protected override void OnAttachedToWindow()
+ {
+ base.OnAttachedToWindow();
+ Control.Enabled = false;
+ Control.Enabled = true;
+ }
+
+ // Workaround for failure to disable text prediction on non-password fields
+ // see https://github.com/xamarin/Xamarin.Forms/issues/10857
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ // Check if changed property is "IsPassword", otherwise ignore
+ if (e.PropertyName == Entry.IsPasswordProperty.PropertyName)
+ {
+ // Check if field type is text, otherwise ignore (numeric passwords, etc.)
+ EditText.InputType = Element.Keyboard.ToInputType();
+ bool isText = (EditText.InputType & InputTypes.ClassText) == InputTypes.ClassText,
+ isNumber = (EditText.InputType & InputTypes.ClassNumber) == InputTypes.ClassNumber;
+ if (isText || isNumber)
+ {
+ if (Element.IsPassword)
+ {
+ // Element is a password field, set inputType to TextVariationPassword which disables
+ // predictive text by default
+ EditText.InputType = EditText.InputType |
+ (isText ? InputTypes.TextVariationPassword : InputTypes.NumberVariationPassword);
+ }
+ else
+ {
+ // Element is not a password field, set inputType to TextVariationVisiblePassword to
+ // disable predictive text while still displaying the content.
+ EditText.InputType = EditText.InputType |
+ (isText ? InputTypes.TextVariationVisiblePassword : InputTypes.NumberVariationNormal);
+ }
+
+ // The workaround above forces a reset of the style properties, so we need to re-apply the font.
+ // see https://xamarin.github.io/bugzilla-archives/33/33666/bug.html
+ var typeface = Typeface.CreateFromAsset(Context.Assets, "RobotoMono_Regular.ttf");
+ if (Control is TextView label)
+ {
+ label.Typeface = typeface;
+ }
+ }
+ }
+ else if (e.PropertyName == Entry.TextColorProperty.PropertyName)
+ {
+ UpdateBorderColor();
+ }
+ }
+
+ private void UpdateBorderColor()
+ {
+ if (Control != null)
+ {
+ var states = new[]
+ {
+ new[] { Android.Resource.Attribute.StateFocused }, // focused
+ new[] { -Android.Resource.Attribute.StateFocused }, // unfocused
+ };
+ var colors = new int[]
+ {
+ ThemeHelpers.PrimaryColor,
+ ThemeHelpers.MutedColor
+ };
+ Control.BackgroundTintList = new ColorStateList(states, colors);
+ }
+ }
+ }
+}
diff --git a/src/Maui/Bitwarden/Platforms/Android/Renderers/CustomLabelRenderer.cs b/src/Maui/Bitwarden/Platforms/Android/Renderers/CustomLabelRenderer.cs
new file mode 100644
index 000000000..1b0514db5
--- /dev/null
+++ b/src/Maui/Bitwarden/Platforms/Android/Renderers/CustomLabelRenderer.cs
@@ -0,0 +1,42 @@
+using System.ComponentModel;
+using Android.Content;
+using Android.OS;
+using Bit.App.Controls;
+using Bit.App.Droid.Renderers;
+using Microsoft.Maui.Controls.Compatibility.Platform.Android;
+using Microsoft.Maui.Controls.Platform;
+
+namespace Bit.App.Droid.Renderers
+{
+ public class CustomLabelRenderer : LabelRenderer
+ {
+ public CustomLabelRenderer(Context context)
+ : base(context)
+ { }
+
+ protected override void OnElementChanged(ElementChangedEventArgs