diff --git a/src/Core/Controls/IconButton.cs b/src/Core/Controls/IconButton.cs
index d27d50626..45ad3c894 100644
--- a/src/Core/Controls/IconButton.cs
+++ b/src/Core/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.ttf";
break;
}
diff --git a/src/Core/Controls/IconLabel.cs b/src/Core/Controls/IconLabel.cs
index 6b5e72308..1b4771f80 100644
--- a/src/Core/Controls/IconLabel.cs
+++ b/src/Core/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.ttf";
break;
}
diff --git a/src/Core/Controls/MiButton.cs b/src/Core/Controls/MiButton.cs
index 99309351b..f345af882 100644
--- a/src/Core/Controls/MiButton.cs
+++ b/src/Core/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.ttf";
break;
}
}
diff --git a/src/Core/Controls/MiLabel.cs b/src/Core/Controls/MiLabel.cs
index 4d510899f..86e838771 100644
--- a/src/Core/Controls/MiLabel.cs
+++ b/src/Core/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.ttf";
break;
}
}
diff --git a/src/Core/Controls/MonoEntry.cs b/src/Core/Controls/MonoEntry.cs
index dfa85d849..a43890492 100644
--- a/src/Core/Controls/MonoEntry.cs
+++ b/src/Core/Controls/MonoEntry.cs
@@ -1,22 +1,14 @@
-using Microsoft.Maui.Controls;
-using Microsoft.Maui;
-
-namespace Bit.App.Controls
+namespace Bit.App.Controls
{
public class MonoEntry : Entry
{
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/Core/Controls/MonoLabel.cs b/src/Core/Controls/MonoLabel.cs
index 6baaf399e..09c760b53 100644
--- a/src/Core/Controls/MonoLabel.cs
+++ b/src/Core/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.ttf";
break;
}
}
diff --git a/src/Core/Pages/Accounts/HomePage.xaml b/src/Core/Pages/Accounts/HomePage.xaml
index 1bace759a..c419ccd15 100644
--- a/src/Core/Pages/Accounts/HomePage.xaml
+++ b/src/Core/Pages/Accounts/HomePage.xaml
@@ -14,7 +14,7 @@
-
+ AutomationId="AccountIconButton" />
-
+
-
-
-
+
diff --git a/src/Core/Pages/Accounts/HomePage.xaml.cs b/src/Core/Pages/Accounts/HomePage.xaml.cs
index eccaaaa1d..91d258781 100644
--- a/src/Core/Pages/Accounts/HomePage.xaml.cs
+++ b/src/Core/Pages/Accounts/HomePage.xaml.cs
@@ -32,7 +32,7 @@ namespace Bit.App.Pages
_vm.StartEnvironmentAction = () => Device.BeginInvokeOnMainThread(async () => await StartEnvironmentAsync());
_vm.CloseAction = async () =>
{
- // await _accountListOverlay.HideAsync();
+ await _accountListOverlay.HideAsync();
await Navigation.PopModalAsync();
};
UpdateLogo();
@@ -43,7 +43,7 @@ namespace Bit.App.Pages
}
if (_appOptions?.HideAccountSwitcher ?? false)
{
- // ToolbarItems.Remove(_accountAvatar);
+ ToolbarItems.Remove(_accountAvatar);
}
}
@@ -56,8 +56,8 @@ namespace Bit.App.Pages
protected override async void OnAppearing()
{
base.OnAppearing();
- // _mainContent.Content = _mainLayout;
- // _accountAvatar?.OnAppearing();
+ _mainContent.Content = _mainLayout;
+ _accountAvatar?.OnAppearing();
if (!_appOptions?.HideAccountSwitcher ?? false)
{
@@ -85,11 +85,11 @@ namespace Bit.App.Pages
protected override bool OnBackButtonPressed()
{
- // if (_accountListOverlay.IsVisible)
- // {
- // _accountListOverlay.HideAsync().FireAndForget();
- // return true;
- // }
+ if (_accountListOverlay.IsVisible)
+ {
+ _accountListOverlay.HideAsync().FireAndForget();
+ return true;
+ }
return false;
}
@@ -97,12 +97,12 @@ namespace Bit.App.Pages
{
base.OnDisappearing();
_broadcasterService.Unsubscribe(nameof(HomePage));
- // _accountAvatar?.OnDisappearing();
+ _accountAvatar?.OnDisappearing();
}
private void UpdateLogo()
{
- // _logo.Source = !ThemeManager.UsingLightTheme ? "logo_white.png" : "logo.png";
+ _logo.Source = !ThemeManager.UsingLightTheme ? "logo_white.png" : "logo.png";
}
private void Cancel_Clicked(object sender, EventArgs e)
@@ -141,7 +141,7 @@ namespace Bit.App.Pages
private async Task StartEnvironmentAsync()
{
- // await _accountListOverlay.HideAsync();
+ await _accountListOverlay.HideAsync();
var page = new EnvironmentPage();
await Navigation.PushModalAsync(new NavigationPage(page));
}
diff --git a/src/Core/Pages/Generator/GeneratorPageViewModel.cs b/src/Core/Pages/Generator/GeneratorPageViewModel.cs
index a589a247d..03f5fcbae 100644
--- a/src/Core/Pages/Generator/GeneratorPageViewModel.cs
+++ b/src/Core/Pages/Generator/GeneratorPageViewModel.cs
@@ -1,19 +1,15 @@
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using System.Windows.Input;
+using System.Windows.Input;
using Bit.App.Abstractions;
-using Bit.Core.Resources.Localization;
using Bit.App.Utilities;
using Bit.Core;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Exceptions;
using Bit.Core.Models.Domain;
+using Bit.Core.Resources.Localization;
using Bit.Core.Utilities;
-using Microsoft.Maui.Controls;
-using Microsoft.Maui;
+#nullable enable
namespace Bit.App.Pages
{
@@ -345,7 +341,7 @@ namespace Bit.App.Pages
get => _usernameOptions.PlusAddressedEmail;
set
{
- if (_usernameOptions.PlusAddressedEmail != value)
+ if (_usernameOptions != null && _usernameOptions.PlusAddressedEmail != value)
{
_usernameOptions.PlusAddressedEmail = value;
TriggerPropertyChanged(nameof(PlusAddressedEmail));
@@ -364,7 +360,7 @@ namespace Bit.App.Pages
});
}
- public bool IsPolicyInEffect => _enforcedPolicyOptions.InEffect();
+ public bool IsPolicyInEffect => _enforcedPolicyOptions?.InEffect() == true;
public GeneratorType GeneratorTypeSelected
{
@@ -375,6 +371,7 @@ namespace Bit.App.Pages
{
IsUsername = value == GeneratorType.Username;
TriggerPropertyChanged(nameof(GeneratorTypeSelected));
+ TriggerPropertyChanged(nameof(UsernameTypeSelected));
SaveOptionsAsync().FireAndForget();
SaveUsernameOptionsAsync().FireAndForget();
}
@@ -398,10 +395,10 @@ namespace Bit.App.Pages
public UsernameType UsernameTypeSelected
{
- get => _usernameOptions.Type;
+ get => _usernameOptions?.Type ?? UsernameType.PlusAddressedEmail;
set
{
- if (_usernameOptions.Type != value)
+ if (_usernameOptions != null && _usernameOptions.Type != value)
{
_usernameOptions.Type = value;
Username = Constants.DefaultUsernameGenerated;
@@ -415,10 +412,10 @@ namespace Bit.App.Pages
public ForwardedEmailServiceType ForwardedEmailServiceSelected
{
- get => _usernameOptions.ServiceType;
+ get => _usernameOptions?.ServiceType ?? ForwardedEmailServiceType.None;
set
{
- if (_usernameOptions.ServiceType != value)
+ if (_usernameOptions != null && _usernameOptions.ServiceType != value)
{
_usernameOptions.ServiceType = value;
Username = Constants.DefaultUsernameGenerated;
@@ -434,10 +431,10 @@ namespace Bit.App.Pages
public string CatchAllEmailDomain
{
- get => _usernameOptions.CatchAllEmailDomain;
+ get => _usernameOptions?.CatchAllEmailDomain;
set
{
- if (_usernameOptions.CatchAllEmailDomain != value)
+ if (_usernameOptions != null && _usernameOptions.CatchAllEmailDomain != value)
{
_usernameOptions.CatchAllEmailDomain = value;
TriggerPropertyChanged(nameof(CatchAllEmailDomain));
@@ -450,6 +447,11 @@ namespace Bit.App.Pages
{
get
{
+ if (_usernameOptions is null)
+ {
+ return null;
+ }
+
switch (ForwardedEmailServiceSelected)
{
case ForwardedEmailServiceType.AnonAddy:
@@ -468,6 +470,11 @@ namespace Bit.App.Pages
}
set
{
+ if (_usernameOptions is null)
+ {
+ return;
+ }
+
bool changed = false;
switch (ForwardedEmailServiceSelected)
{
@@ -548,10 +555,10 @@ namespace Bit.App.Pages
public string AddyIoDomainName
{
- get => _usernameOptions.AnonAddyDomainName;
+ get => _usernameOptions?.AnonAddyDomainName;
set
{
- if (_usernameOptions.AnonAddyDomainName != value)
+ if (_usernameOptions != null && _usernameOptions.AnonAddyDomainName != value)
{
_usernameOptions.AnonAddyDomainName = value;
TriggerPropertyChanged(nameof(AddyIoDomainName));
@@ -562,10 +569,10 @@ namespace Bit.App.Pages
public bool CapitalizeRandomWordUsername
{
- get => _usernameOptions.CapitalizeRandomWordUsername;
+ get => _usernameOptions?.CapitalizeRandomWordUsername == true;
set
{
- if (_usernameOptions.CapitalizeRandomWordUsername != value)
+ if (_usernameOptions != null && _usernameOptions.CapitalizeRandomWordUsername != value)
{
_usernameOptions.CapitalizeRandomWordUsername = value;
TriggerPropertyChanged(nameof(CapitalizeRandomWordUsername));
@@ -576,10 +583,10 @@ namespace Bit.App.Pages
public bool IncludeNumberRandomWordUsername
{
- get => _usernameOptions.IncludeNumberRandomWordUsername;
+ get => _usernameOptions?.IncludeNumberRandomWordUsername == true;
set
{
- if (_usernameOptions.IncludeNumberRandomWordUsername != value)
+ if (_usernameOptions != null && _usernameOptions.IncludeNumberRandomWordUsername != value)
{
_usernameOptions.IncludeNumberRandomWordUsername = value;
TriggerPropertyChanged(nameof(IncludeNumberRandomWordUsername));
@@ -590,10 +597,10 @@ namespace Bit.App.Pages
public UsernameEmailType PlusAddressedEmailTypeSelected
{
- get => _usernameOptions.PlusAddressedEmailType;
+ get => _usernameOptions?.PlusAddressedEmailType ?? UsernameEmailType.Random;
set
{
- if (_usernameOptions.PlusAddressedEmailType != value)
+ if (_usernameOptions != null && _usernameOptions.PlusAddressedEmailType != value)
{
_usernameOptions.PlusAddressedEmailType = value;
TriggerPropertyChanged(nameof(PlusAddressedEmailTypeSelected));
@@ -604,10 +611,10 @@ namespace Bit.App.Pages
public UsernameEmailType CatchAllEmailTypeSelected
{
- get => _usernameOptions.CatchAllEmailType;
+ get => _usernameOptions?.CatchAllEmailType ?? UsernameEmailType.Random;
set
{
- if (_usernameOptions.CatchAllEmailType != value)
+ if (_usernameOptions != null && _usernameOptions.CatchAllEmailType != value)
{
_usernameOptions.CatchAllEmailType = value;
TriggerPropertyChanged(nameof(CatchAllEmailTypeSelected));
diff --git a/src/Core/Pages/Send/SendAddEditPage.xaml b/src/Core/Pages/Send/SendAddEditPage.xaml
index 74b50e17f..fc58cd30c 100644
--- a/src/Core/Pages/Send/SendAddEditPage.xaml
+++ b/src/Core/Pages/Send/SendAddEditPage.xaml
@@ -258,10 +258,11 @@
-
@@ -196,7 +196,7 @@
Grid.RowSpan="2"
AutomationProperties.IsInAccessibleTree="True"
SemanticProperties.Description="{u:I18n CheckPassword}"
- IsVisible="{Binding Cipher.ViewPassword}"
+ IsVisible="{Binding Cipher.ViewPassword, FallbackValue=False}"
AutomationId="CheckPasswordButton" />
-
+
@@ -253,8 +253,6 @@
IsVisible="{Binding HasTotpValue, Converter={StaticResource inverseBool}}"
Margin="0,5,0,0"
StyleClass="btn-icon-row"
- HorizontalOptions="FillAndExpand"
- VerticalOptions="FillAndExpand"
Padding="0"
Grid.Row="1"
Grid.Column="0"
@@ -272,12 +270,12 @@
@@ -336,7 +334,7 @@
Grid.Column="0" />
-
-
+
+
-
+
@@ -695,8 +693,8 @@
AutomationId="LoginUriOptionsButton" />
-
-
+
+
@@ -723,7 +721,7 @@
StyleClass="box-label-regular"
HorizontalOptions="StartAndExpand" />
@@ -741,7 +739,7 @@
SemanticProperties.Description="{u:I18n MasterPasswordRePromptHelp}"
HorizontalOptions="StartAndExpand" />
@@ -799,7 +797,7 @@
StyleClass="box-label" />
diff --git a/src/Core/Pages/Vault/CipherAddEditPageViewModel.cs b/src/Core/Pages/Vault/CipherAddEditPageViewModel.cs
index e6efb8f70..bd34ca08f 100644
--- a/src/Core/Pages/Vault/CipherAddEditPageViewModel.cs
+++ b/src/Core/Pages/Vault/CipherAddEditPageViewModel.cs
@@ -288,7 +288,7 @@ namespace Bit.App.Pages
nameof(ShowCollections)
});
}
- public bool ShowCollections => (!EditMode || CloneMode) && Cipher.OrganizationId != null;
+ public bool ShowCollections => (!EditMode || CloneMode) && Cipher?.OrganizationId != null;
public bool EditMode => !string.IsNullOrWhiteSpace(CipherId);
public bool ShowOwnershipOptions => !EditMode || CloneMode;
public bool OwnershipPolicyInEffect => ShowOwnershipOptions && !AllowPersonal;
@@ -298,15 +298,15 @@ namespace Bit.App.Pages
public bool IsIdentity => Cipher?.Type == CipherType.Identity;
public bool IsCard => Cipher?.Type == CipherType.Card;
public bool IsSecureNote => Cipher?.Type == CipherType.SecureNote;
- public bool ShowUris => IsLogin && Cipher.Login.HasUris;
- public bool ShowAttachments => Cipher.HasAttachments;
+ public bool ShowUris => IsLogin && Cipher != null && Cipher.Login.HasUris;
+ public bool ShowAttachments => Cipher != null && Cipher.HasAttachments;
public string ShowPasswordIcon => ShowPassword ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye;
public string ShowCardNumberIcon => ShowCardNumber ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye;
public string ShowCardCodeIcon => ShowCardCode ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye;
- public int PasswordFieldColSpan => Cipher.ViewPassword ? 1 : 4;
- public int TotpColumnSpan => Cipher.ViewPassword ? 1 : 2;
+ public int PasswordFieldColSpan => Cipher != null && Cipher.ViewPassword ? 1 : 4;
+ public int TotpColumnSpan => Cipher != null && Cipher.ViewPassword ? 1 : 2;
public bool AllowPersonal { get; set; }
- public bool PasswordPrompt => Cipher.Reprompt != CipherRepromptType.None;
+ public bool PasswordPrompt => Cipher != null && Cipher.Reprompt != CipherRepromptType.None;
public string PasswordVisibilityAccessibilityText => ShowPassword ? AppResources.PasswordIsVisibleTapToHide : AppResources.PasswordIsNotVisibleTapToShow;
public bool HasTotpValue => IsLogin && !string.IsNullOrEmpty(Cipher?.Login?.Totp);
public string SetupTotpText => $"{BitwardenIcons.Camera} {AppResources.SetupTotp}";
@@ -459,6 +459,12 @@ namespace Bit.App.Pages
}
_previousCipherId = CipherId;
+ MainThread.BeginInvokeOnMainThread(() =>
+ {
+ TriggerPropertyChanged(nameof(OwnershipOptions));
+ TriggerPropertyChanged(nameof(OwnershipSelectedIndex));
+ });
+
return true;
}
@@ -892,7 +898,7 @@ namespace Bit.App.Pages
private void TriggerCipherChanged()
{
- TriggerPropertyChanged(nameof(Cipher), AdditionalPropertiesToRaiseOnCipherChanged);
+ MainThread.BeginInvokeOnMainThread(() => TriggerPropertyChanged(nameof(Cipher), AdditionalPropertiesToRaiseOnCipherChanged));
}
private async Task CopyTotpClipboardAsync()
diff --git a/src/Core/Pages/Vault/CipherDetailsPageViewModel.cs b/src/Core/Pages/Vault/CipherDetailsPageViewModel.cs
index 5ee8101af..4e122993d 100644
--- a/src/Core/Pages/Vault/CipherDetailsPageViewModel.cs
+++ b/src/Core/Pages/Vault/CipherDetailsPageViewModel.cs
@@ -198,11 +198,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/Core/Utilities/AsyncCommand.cs b/src/Core/Utilities/AsyncCommand.cs
index 9b1516f38..cc81ed0b2 100644
--- a/src/Core/Utilities/AsyncCommand.cs
+++ b/src/Core/Utilities/AsyncCommand.cs
@@ -27,7 +27,12 @@ namespace Bit.App.Utilities
}
}
- _relayCommand = new AsyncRelayCommand(doAsync, canExecute, allowsMultipleExecutions ? AsyncRelayCommandOptions.AllowConcurrentExecutions : AsyncRelayCommandOptions.None);
+ var safeCanExecute = canExecute;
+ if (canExecute is null)
+ {
+ safeCanExecute = () => true;
+ }
+ _relayCommand = new AsyncRelayCommand(doAsync, safeCanExecute, allowsMultipleExecutions ? AsyncRelayCommandOptions.AllowConcurrentExecutions : AsyncRelayCommandOptions.None);
}
public event EventHandler CanExecuteChanged;
@@ -58,7 +63,12 @@ namespace Bit.App.Utilities
}
}
- _relayCommand = new AsyncRelayCommand(doAsync, canExecute, allowsMultipleExecutions ? AsyncRelayCommandOptions.AllowConcurrentExecutions : AsyncRelayCommandOptions.None);
+ var safeCanExecute = canExecute;
+ if (canExecute is null)
+ {
+ safeCanExecute = _ => true;
+ }
+ _relayCommand = new AsyncRelayCommand(doAsync, safeCanExecute, allowsMultipleExecutions ? AsyncRelayCommandOptions.AllowConcurrentExecutions : AsyncRelayCommandOptions.None);
}
public event EventHandler CanExecuteChanged;
diff --git a/src/Core/Utilities/LocalizableEnumConverter.cs b/src/Core/Utilities/LocalizableEnumConverter.cs
index 1da0cf1ba..fe267b345 100644
--- a/src/Core/Utilities/LocalizableEnumConverter.cs
+++ b/src/Core/Utilities/LocalizableEnumConverter.cs
@@ -12,7 +12,7 @@ namespace Bit.App.Utilities
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
- return EnumHelper.GetLocalizedValue(value, value.GetType());
+ return value != null ? EnumHelper.GetLocalizedValue(value, value.GetType()) : string.Empty;
}
public object ConvertBack(object value, Type targetType, object parameter,