diff --git a/src/App/Pages/Accounts/TwoFactorPage.xaml b/src/App/Pages/Accounts/TwoFactorPage.xaml
index 8a2eea9c6..c4f4666d2 100644
--- a/src/App/Pages/Accounts/TwoFactorPage.xaml
+++ b/src/App/Pages/Accounts/TwoFactorPage.xaml
@@ -17,15 +17,19 @@
-
+
-
+
("stateService");
_i18nService = ServiceContainer.Resolve("i18nService");
_appIdService = ServiceContainer.Resolve("appIdService");
+ _logger = ServiceContainer.Resolve();
PageTitle = AppResources.TwoStepLogin;
SubmitCommand = new Command(async () => await SubmitAsync());
+ MoreCommand = new AsyncCommand(MoreAsync, onException: _logger.Exception, allowsMultipleExecutions: false);
}
public string TotpInstruction
@@ -111,6 +116,7 @@ namespace Bit.App.Pages
});
}
public Command SubmitCommand { get; }
+ public ICommand MoreCommand { get; }
public Action TwoFactorAuthSuccessAction { get; set; }
public Action StartSetPasswordAction { get; set; }
public Action CloseAction { get; set; }
@@ -337,6 +343,15 @@ namespace Bit.App.Pages
}
}
+ private async Task MoreAsync()
+ {
+ var selection = await _deviceActionService.DisplayActionSheetAsync(AppResources.Options, AppResources.Cancel, null, AppResources.UseAnotherTwoStepMethod);
+ if (selection == AppResources.UseAnotherTwoStepMethod)
+ {
+ await AnotherMethodAsync();
+ }
+ }
+
public async Task AnotherMethodAsync()
{
var supportedProviders = _authService.GetSupportedTwoFactorProviders();
diff --git a/src/iOS.Autofill/CredentialProviderViewController.cs b/src/iOS.Autofill/CredentialProviderViewController.cs
index 9bd087f17..269f4d039 100644
--- a/src/iOS.Autofill/CredentialProviderViewController.cs
+++ b/src/iOS.Autofill/CredentialProviderViewController.cs
@@ -18,6 +18,7 @@ using CoreNFC;
using Foundation;
using UIKit;
using Xamarin.Forms;
+using Xamarin.Forms.Platform.iOS;
namespace Bit.iOS.Autofill
{
diff --git a/src/iOS.Autofill/iOS.Autofill.csproj b/src/iOS.Autofill/iOS.Autofill.csproj
index 451361ac6..f1cec9d61 100644
--- a/src/iOS.Autofill/iOS.Autofill.csproj
+++ b/src/iOS.Autofill/iOS.Autofill.csproj
@@ -253,6 +253,17 @@
+
+
+ Resources\more_vert.png
+
+
+ Resources\more_vert%402x.png
+
+
+ Resources\more_vert%403x.png
+
+
4.4.0
diff --git a/src/iOS.Core/Services/DeviceActionService.cs b/src/iOS.Core/Services/DeviceActionService.cs
index 22701bc73..71546f4ae 100644
--- a/src/iOS.Core/Services/DeviceActionService.cs
+++ b/src/iOS.Core/Services/DeviceActionService.cs
@@ -84,6 +84,12 @@ namespace Bit.iOS.Core.Services
HideLoadingAsync().GetAwaiter().GetResult();
}
+ var vc = GetPresentedViewController();
+ if (vc is null)
+ {
+ return Task.CompletedTask;
+ }
+
var result = new TaskCompletionSource();
var loadingIndicator = new UIActivityIndicatorView(new CGRect(10, 5, 50, 50));
@@ -96,8 +102,7 @@ namespace Bit.iOS.Core.Services
_progressAlert.View.TintColor = UIColor.Black;
_progressAlert.View.Add(loadingIndicator);
- var vc = GetPresentedViewController();
- vc?.PresentViewController(_progressAlert, false, () => result.TrySetResult(0));
+ vc.PresentViewController(_progressAlert, false, () => result.TrySetResult(0));
return result.Task;
}
@@ -205,6 +210,12 @@ namespace Bit.iOS.Core.Services
string text = null, string okButtonText = null, string cancelButtonText = null,
bool numericKeyboard = false, bool autofocus = true, bool password = false)
{
+ var vc = GetPresentedViewController();
+ if (vc is null)
+ {
+ return null;
+ }
+
var result = new TaskCompletionSource();
var alert = UIAlertController.Create(title ?? string.Empty, description, UIAlertControllerStyle.Alert);
UITextField input = null;
@@ -234,8 +245,7 @@ namespace Bit.iOS.Core.Services
input.KeyboardAppearance = UIKeyboardAppearance.Dark;
}
});
- var vc = GetPresentedViewController();
- vc?.PresentViewController(alert, true, null);
+ vc.PresentViewController(alert, true, null);
return result.Task;
}
@@ -312,6 +322,12 @@ namespace Bit.iOS.Core.Services
public Task DisplayAlertAsync(string title, string message, string cancel, params string[] buttons)
{
+ var vc = GetPresentedViewController();
+ if (vc is null)
+ {
+ return null;
+ }
+
var result = new TaskCompletionSource();
var alert = UIAlertController.Create(title ?? string.Empty, message, UIAlertControllerStyle.Alert);
if (!string.IsNullOrWhiteSpace(cancel))
@@ -328,8 +344,7 @@ namespace Bit.iOS.Core.Services
result.TrySetResult(button);
}));
}
- var vc = GetPresentedViewController();
- vc?.PresentViewController(alert, true, null);
+ vc.PresentViewController(alert, true, null);
return result.Task;
}
@@ -340,8 +355,12 @@ namespace Bit.iOS.Core.Services
{
return app.MainPage.DisplayActionSheet(title, cancel, destruction, buttons);
}
- var result = new TaskCompletionSource();
var vc = GetPresentedViewController();
+ if (vc is null)
+ {
+ return null;
+ }
+ var result = new TaskCompletionSource();
var sheet = UIAlertController.Create(title, null, UIAlertControllerStyle.ActionSheet);
if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad)
{
diff --git a/src/iOS.Extension/iOS.Extension.csproj b/src/iOS.Extension/iOS.Extension.csproj
index 8907ca640..d11ce857b 100644
--- a/src/iOS.Extension/iOS.Extension.csproj
+++ b/src/iOS.Extension/iOS.Extension.csproj
@@ -230,6 +230,15 @@
+
+ Resources\more_vert.png
+
+
+ Resources\more_vert%402x.png
+
+
+ Resources\more_vert%403x.png
+
diff --git a/src/iOS.ShareExtension/iOS.ShareExtension.csproj b/src/iOS.ShareExtension/iOS.ShareExtension.csproj
index 5109c8886..37c743f11 100644
--- a/src/iOS.ShareExtension/iOS.ShareExtension.csproj
+++ b/src/iOS.ShareExtension/iOS.ShareExtension.csproj
@@ -227,6 +227,15 @@
Resources\logo.png
+
+ Resources\more_vert.png
+
+
+ Resources\more_vert%402x.png
+
+
+ Resources\more_vert%403x.png
+
Resources\bwi-font.ttf