1
0
mirror of https://github.com/bitwarden/mobile.git synced 2024-09-19 02:41:31 +02:00

PM-3350 Fix iOS extensions navigation and Window/RootViewController handling for TapGestureRecognizer to work

This commit is contained in:
Federico Maccaroni 2023-12-07 17:40:20 -03:00
parent a5888827c9
commit a4a3d31c19
No known key found for this signature in database
GPG Key ID: 5D233F8F2B034536
11 changed files with 279 additions and 149 deletions

View File

@ -0,0 +1,51 @@
#if ENABLED_TAP_GESTURE_RECOGNIZER_MAUI_EMBEDDED_WORKAROUND
using System;
using AuthenticationServices;
using Bit.App.Abstractions;
using Bit.Core.Utilities;
using Bit.iOS.Autofill.Models;
using Bit.iOS.Core.Utilities;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using UIKit;
namespace Bit.iOS.Autofill
{
public partial class CredentialProviderViewController : ASCredentialProviderViewController, IAccountsManagerHost
{
const string STORYBOARD_NAME = "MainInterface";
Lazy<UIStoryboard> _storyboard = new Lazy<UIStoryboard>(() => UIStoryboard.FromName(STORYBOARD_NAME, null));
public void InitWithContext(Context context)
{
_context = context;
}
public void DismissLockAndContinue()
{
if (UIApplication.SharedApplication.KeyWindow is null)
{
return;
}
UIApplication.SharedApplication.KeyWindow.RootViewController = _storyboard.Value.InstantiateInitialViewController();
if (UIApplication.SharedApplication.KeyWindow?.RootViewController is CredentialProviderViewController cpvc)
{
cpvc.InitWithContext(_context);
cpvc.OnLockDismissedAsync().FireAndForget();
}
}
private void NavigateToPage(ContentPage page)
{
var navigationPage = new NavigationPage(page);
var window = new Window(navigationPage);
window.ToHandler(MauiContextSingleton.Instance.MauiContext);
}
}
}
#endif

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using AuthenticationServices; using AuthenticationServices;
using Bit.App.Abstractions; using Bit.App.Abstractions;
@ -16,8 +17,7 @@ using Bit.iOS.Core.Views;
using CoreFoundation; using CoreFoundation;
using CoreNFC; using CoreNFC;
using Foundation; using Foundation;
using Microsoft.Maui.Controls; using Microsoft.Maui.ApplicationModel;
using Microsoft.Maui.Platform;
using UIKit; using UIKit;
namespace Bit.iOS.Autofill namespace Bit.iOS.Autofill
@ -29,7 +29,7 @@ namespace Bit.iOS.Autofill
private Core.NFCReaderDelegate _nfcDelegate = null; private Core.NFCReaderDelegate _nfcDelegate = null;
private IAccountsManager _accountsManager; private IAccountsManager _accountsManager;
private readonly LazyResolve<IStateService> _stateService = new LazyResolve<IStateService>("stateService"); private readonly LazyResolve<IStateService> _stateService = new LazyResolve<IStateService>();
public CredentialProviderViewController(IntPtr handle) public CredentialProviderViewController(IntPtr handle)
: base(handle) : base(handle)
@ -37,11 +37,13 @@ namespace Bit.iOS.Autofill
ModalPresentationStyle = UIModalPresentationStyle.FullScreen; ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
} }
private ASCredentialProviderExtensionContext ASExtensionContext => _context?.ExtContext as ASCredentialProviderExtensionContext;
public override void ViewDidLoad() public override void ViewDidLoad()
{ {
try try
{ {
InitApp(); InitAppIfNeeded();
base.ViewDidLoad(); base.ViewDidLoad();
@ -51,6 +53,7 @@ namespace Bit.iOS.Autofill
{ {
ExtContext = ExtensionContext ExtContext = ExtensionContext
}; };
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -171,7 +174,7 @@ namespace Bit.iOS.Autofill
if ((_context?.Configuring ?? true) && string.IsNullOrWhiteSpace(password)) if ((_context?.Configuring ?? true) && string.IsNullOrWhiteSpace(password))
{ {
ServiceContainer.Reset(); ServiceContainer.Reset();
ExtensionContext?.CompleteExtensionConfigurationRequest(); ASExtensionContext?.CompleteExtensionConfigurationRequest();
return; return;
} }
@ -180,7 +183,7 @@ namespace Bit.iOS.Autofill
ServiceContainer.Reset(); ServiceContainer.Reset();
var err = new NSError(new NSString("ASExtensionErrorDomain"), var err = new NSError(new NSString("ASExtensionErrorDomain"),
Convert.ToInt32(ASExtensionErrorCode.UserCanceled), null); Convert.ToInt32(ASExtensionErrorCode.UserCanceled), null);
NSRunLoop.Main.BeginInvokeOnMainThread(() => ExtensionContext?.CancelRequest(err)); NSRunLoop.Main.BeginInvokeOnMainThread(() => ASExtensionContext?.CancelRequest(err));
return; return;
} }
@ -198,7 +201,7 @@ namespace Bit.iOS.Autofill
await eventService.CollectAsync(Bit.Core.Enums.EventType.Cipher_ClientAutofilled, id); await eventService.CollectAsync(Bit.Core.Enums.EventType.Cipher_ClientAutofilled, id);
} }
ServiceContainer.Reset(); ServiceContainer.Reset();
ExtensionContext?.CompleteRequest(cred, null); ASExtensionContext?.CompleteRequest(cred, null);
}); });
} }
@ -245,30 +248,46 @@ namespace Bit.iOS.Autofill
} }
} }
public void DismissLockAndContinue() #if !ENABLED_TAP_GESTURE_RECOGNIZER_MAUI_EMBEDDED_WORKAROUND
public async void DismissLockAndContinue()
{ {
DismissViewController(false, async () => ClipLogger.Log("Dismiss lock and continue");
DismissViewController(false, async () => await OnLockDismissedAsync());
}
private void NavigateToPage(ContentPage page)
{
var navigationPage = new NavigationPage(page);
var uiController = navigationPage.ToUIViewController(MauiContextSingleton.Instance.MauiContext);
uiController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
PresentViewController(uiController, true, null);
}
#endif
public async Task OnLockDismissedAsync()
{ {
try try
{ {
if (_context.CredentialIdentity != null) if (_context.CredentialIdentity != null)
{ {
await ProvideCredentialAsync(); await MainThread.InvokeOnMainThreadAsync(() => ProvideCredentialAsync());
return; return;
} }
if (_context.Configuring) if (_context.Configuring)
{ {
PerformSegue("setupSegue", this); await MainThread.InvokeOnMainThreadAsync(() => PerformSegue("setupSegue", this));
return; return;
} }
if (_context.ServiceIdentifiers == null || _context.ServiceIdentifiers.Length == 0) if (_context.ServiceIdentifiers == null || _context.ServiceIdentifiers.Length == 0)
{ {
PerformSegue("loginSearchSegue", this); await MainThread.InvokeOnMainThreadAsync(() => PerformSegue("loginSearchSegue", this));
} }
else else
{ {
PerformSegue("loginListSegue", this); await MainThread.InvokeOnMainThreadAsync(() => PerformSegue("loginListSegue", this));
} }
} }
catch (Exception ex) catch (Exception ex)
@ -276,7 +295,6 @@ namespace Bit.iOS.Autofill
LoggerHelper.LogEvenIfCantBeResolved(ex); LoggerHelper.LogEvenIfCantBeResolved(ex);
throw; throw;
} }
});
} }
private async Task ProvideCredentialAsync(bool userInteraction = true) private async Task ProvideCredentialAsync(bool userInteraction = true)
@ -407,22 +425,7 @@ namespace Bit.iOS.Autofill
} }
} }
private void NavigateToPage(ContentPage page)
{
var navigationPage = new NavigationPage(page);
var window = new Window(navigationPage);
window.ToHandler(MauiContextSingleton.Instance.MauiContext);
var uiController = navigationPage.ToUIViewController(MauiContextSingleton.Instance.MauiContext);
uiController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
PresentViewController(uiController, true, null);
}
private void LaunchHomePage() private void LaunchHomePage()
{
try
{ {
var appOptions = new AppOptions { IosExtension = true }; var appOptions = new AppOptions { IosExtension = true };
var homePage = new HomePage(appOptions); var homePage = new HomePage(appOptions);
@ -442,12 +445,6 @@ namespace Bit.iOS.Autofill
LogoutIfAuthed(); LogoutIfAuthed();
} }
catch (Exception ex)
{
UIPasteboard.General.String = ex.ToString();
_labelErr.Text = ex.ToString();
}
}
private void LaunchEnvironmentFlow() private void LaunchEnvironmentFlow()
{ {

View File

@ -12,9 +12,6 @@ namespace Bit.iOS.Autofill
[Register ("CredentialProviderViewController")] [Register ("CredentialProviderViewController")]
partial class CredentialProviderViewController partial class CredentialProviderViewController
{ {
[Outlet]
UIKit.UILabel _labelErr { get; set; }
[Outlet] [Outlet]
[GeneratedCode ("iOS Designer", "1.0")] [GeneratedCode ("iOS Designer", "1.0")]
UIKit.UIImageView Logo { get; set; } UIKit.UIImageView Logo { get; set; }
@ -25,11 +22,6 @@ namespace Bit.iOS.Autofill
Logo.Dispose (); Logo.Dispose ();
Logo = null; Logo = null;
} }
if (_labelErr != null) {
_labelErr.Dispose ();
_labelErr = null;
}
} }
} }
} }

View File

@ -18,28 +18,18 @@
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews> <subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="logo.png" translatesAutoresizingMaskIntoConstraints="NO" id="1713"> <imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="logo.png" translatesAutoresizingMaskIntoConstraints="NO" id="1713">
<rect key="frame" x="66" y="676" width="282" height="44"/> <rect key="frame" x="66" y="396" width="282" height="44"/>
</imageView> </imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="No Error" textAlignment="natural" lineBreakMode="characterWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HVp-Yu-JIZ">
<rect key="frame" x="5" y="187" width="404" height="26.5"/>
<fontDescription key="fontDescription" type="system" pointSize="22"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews> </subviews>
<viewLayoutGuide key="safeArea" id="YG6-2d-qpF"/> <viewLayoutGuide key="safeArea" id="YG6-2d-qpF"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints> <constraints>
<constraint firstItem="1713" firstAttribute="centerY" secondItem="44" secondAttribute="centerY" constant="250" id="1763"/> <constraint firstItem="1713" firstAttribute="centerY" secondItem="44" secondAttribute="centerY" constant="-30" id="1763"/>
<constraint firstItem="1713" firstAttribute="centerX" secondItem="YG6-2d-qpF" secondAttribute="centerX" id="1764"/> <constraint firstItem="1713" firstAttribute="centerX" secondItem="YG6-2d-qpF" secondAttribute="centerX" id="1764"/>
<constraint firstItem="HVp-Yu-JIZ" firstAttribute="top" secondItem="YG6-2d-qpF" secondAttribute="top" constant="139" id="Ay0-v3-kTO"/>
<constraint firstItem="HVp-Yu-JIZ" firstAttribute="trailing" secondItem="YG6-2d-qpF" secondAttribute="trailing" constant="-5" id="TdY-Cu-YFt"/>
<constraint firstItem="YG6-2d-qpF" firstAttribute="leading" secondItem="HVp-Yu-JIZ" secondAttribute="leading" constant="-5" id="lfV-6C-INq"/>
</constraints> </constraints>
</view> </view>
<connections> <connections>
<outlet property="Logo" destination="1713" id="name-outlet-1713"/> <outlet property="Logo" destination="1713" id="name-outlet-1713"/>
<outlet property="_labelErr" destination="HVp-Yu-JIZ" id="PjY-be-dhX"/>
<segue destination="oCZ-GQ-aOK" kind="show" identifier="loginListSegue" id="1679"/> <segue destination="oCZ-GQ-aOK" kind="show" identifier="loginListSegue" id="1679"/>
<segue destination="6855" kind="presentation" identifier="lockPasswordSegue" id="9874"/> <segue destination="6855" kind="presentation" identifier="lockPasswordSegue" id="9874"/>
<segue destination="10580" kind="presentation" identifier="setupSegue" modalTransitionStyle="coverVertical" id="11089"/> <segue destination="10580" kind="presentation" identifier="setupSegue" modalTransitionStyle="coverVertical" id="11089"/>

View File

@ -10,6 +10,8 @@
<EnableDefaultCompileItems>False</EnableDefaultCompileItems> <EnableDefaultCompileItems>False</EnableDefaultCompileItems>
<DefineConstants>$(DefineConstants);ENABLED_TAP_GESTURE_RECOGNIZER_MAUI_EMBEDDED_WORKAROUND</DefineConstants>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">12.0</SupportedOSPlatformVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">12.0</SupportedOSPlatformVersion>
</PropertyGroup> </PropertyGroup>
@ -78,6 +80,7 @@
<Compile Include="Models\Context.cs" /> <Compile Include="Models\Context.cs" />
<BundleResource Include="Resources\MaterialIcons_Regular.ttf" /> <BundleResource Include="Resources\MaterialIcons_Regular.ttf" />
<BundleResource Include="Resources\bwi-font.ttf" /> <BundleResource Include="Resources\bwi-font.ttf" />
<Compile Include="CredentialProviderViewController.TapGestureHack.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<BundleResource Include="Resources\check.png" /> <BundleResource Include="Resources\check.png" />

View File

@ -0,0 +1,68 @@
#if ENABLED_TAP_GESTURE_RECOGNIZER_MAUI_EMBEDDED_WORKAROUND
using System;
using System.Linq;
using Bit.iOS.Core.Utilities;
using Bit.iOS.Extension.Models;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using UIKit;
namespace Bit.iOS.Extension
{
public partial class LoadingViewController : UIViewController
{
const string STORYBOARD_NAME = "MainInterface";
Lazy<UIStoryboard> _storyboard = new Lazy<UIStoryboard>(() => UIStoryboard.FromName(STORYBOARD_NAME, null));
public void InitWithContext(Context context)
{
ClipLogger.Log($"InitWithContext: {context?.UrlString}");
_context = context;
_shouldInitialize = false;
}
public void DismissLockAndContinue()
{
ClipLogger.Log("DismissLockAndContinue");
if (UIApplication.SharedApplication.KeyWindow is null)
{
ClipLogger.Log("KeyWindow is null");
return;
}
UIApplication.SharedApplication.KeyWindow.RootViewController = _storyboard.Value.InstantiateInitialViewController();
if (UIApplication.SharedApplication.KeyWindow?.RootViewController is UINavigationController navContr)
{
var rootVC = navContr.ViewControllers.FirstOrDefault();
if (rootVC is LoadingViewController loadingVC)
{
ClipLogger.Log("Re-initing");
loadingVC.InitWithContext(_context);
loadingVC.ContinueOn();
}
else
{
ClipLogger.Log($"Not LVC: {rootVC?.GetType().FullName}");
}
}
else
{
ClipLogger.Log($"DismissLockAndContinue RVC not correct: {UIApplication.SharedApplication.KeyWindow?.RootViewController?.GetType().FullName}");
}
ClipLogger.Log("DismissLockAndContinue Done");
}
private void NavigateToPage(ContentPage page)
{
ClipLogger.Log($"NavigateToPage {page?.GetType().FullName}");
var navigationPage = new NavigationPage(page);
var window = new Window(navigationPage);
window.ToHandler(MauiContextSingleton.Instance.MauiContext);
}
}
}
#endif

View File

@ -12,15 +12,12 @@ using Bit.Core.Enums;
using Bit.Core.Services; using Bit.Core.Services;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Bit.iOS.Core; using Bit.iOS.Core;
using Bit.iOS.Core.Controllers;
using Bit.iOS.Core.Models; using Bit.iOS.Core.Models;
using Bit.iOS.Core.Utilities; using Bit.iOS.Core.Utilities;
using Bit.iOS.Core.Views; using Bit.iOS.Core.Views;
using Bit.iOS.Extension.Models; using Bit.iOS.Extension.Models;
using CoreNFC; using CoreNFC;
using Foundation; using Foundation;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using MobileCoreServices; using MobileCoreServices;
using UIKit; using UIKit;
@ -32,6 +29,8 @@ namespace Bit.iOS.Extension
private NFCNdefReaderSession _nfcSession = null; private NFCNdefReaderSession _nfcSession = null;
private Core.NFCReaderDelegate _nfcDelegate = null; private Core.NFCReaderDelegate _nfcDelegate = null;
private bool _shouldInitialize = true;
public LoadingViewController(IntPtr handle) public LoadingViewController(IntPtr handle)
: base(handle) : base(handle)
{ } { }
@ -44,8 +43,14 @@ namespace Bit.iOS.Extension
base.ViewDidLoad(); base.ViewDidLoad();
Logo.Image = new UIImage(ThemeHelpers.LightTheme ? "logo.png" : "logo_white.png"); Logo.Image = new UIImage(ThemeHelpers.LightTheme ? "logo.png" : "logo_white.png");
View.BackgroundColor = ThemeHelpers.SplashBackgroundColor; View.BackgroundColor = ThemeHelpers.SplashBackgroundColor;
if (!_shouldInitialize)
{
return;
}
_context.ExtContext = ExtensionContext; _context.ExtContext = ExtensionContext;
foreach (var item in ExtensionContext.InputItems) foreach (var item in _context.ExtContext.InputItems)
{ {
var processed = false; var processed = false;
foreach (var itemProvider in item.Attachments) foreach (var itemProvider in item.Attachments)
@ -77,6 +82,11 @@ namespace Bit.iOS.Extension
public override async void ViewDidAppear(bool animated) public override async void ViewDidAppear(bool animated)
{ {
if (!_shouldInitialize)
{
return;
}
try try
{ {
base.ViewDidAppear(animated); base.ViewDidAppear(animated);
@ -111,6 +121,7 @@ namespace Bit.iOS.Extension
{ {
if (navController.TopViewController is LoginListViewController listLoginController) if (navController.TopViewController is LoginListViewController listLoginController)
{ {
listLoginController.Context = _context; listLoginController.Context = _context;
listLoginController.LoadingController = this; listLoginController.LoadingController = this;
segue.DestinationViewController.PresentationController.Delegate = segue.DestinationViewController.PresentationController.Delegate =
@ -140,12 +151,23 @@ namespace Bit.iOS.Extension
} }
} }
#if !ENABLED_TAP_GESTURE_RECOGNIZER_MAUI_EMBEDDED_WORKAROUND
public void DismissLockAndContinue() public void DismissLockAndContinue()
{ {
Debug.WriteLine("BW Log, Dismissing lock controller."); Debug.WriteLine("BW Log, Dismissing lock controller.");
DismissViewController(false, () => ContinueOn()); DismissViewController(false, () => ContinueOn());
} }
private void NavigateToPage(ContentPage page)
{
var navigationPage = new NavigationPage(page);
var uiController = navigationPage.ToUIViewController(MauiContextSingleton.Instance.MauiContext);
uiController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
PresentViewController(uiController, true, null);
}
#endif
private void ContinueOn() private void ContinueOn()
{ {
Debug.WriteLine("BW Log, Segue to setup, login add or list."); Debug.WriteLine("BW Log, Segue to setup, login add or list.");
@ -221,7 +243,7 @@ namespace Bit.iOS.Extension
await eventService.CollectAsync(Bit.Core.Enums.EventType.Cipher_ClientAutofilled, id); await eventService.CollectAsync(Bit.Core.Enums.EventType.Cipher_ClientAutofilled, id);
} }
ServiceContainer.Reset(); ServiceContainer.Reset();
ExtensionContext?.CompleteRequest(returningItems, null); _context?.ExtContext?.CompleteRequest(returningItems, null);
}); });
} }
@ -413,6 +435,11 @@ namespace Bit.iOS.Extension
private void InitApp() private void InitApp()
{ {
if (!_shouldInitialize)
{
return;
}
// TODO: Change for iOSCoreHelpers.InitApp(...) when implementing IAccountsManager here // TODO: Change for iOSCoreHelpers.InitApp(...) when implementing IAccountsManager here
iOSCoreHelpers.SetupMaui(); iOSCoreHelpers.SetupMaui();
@ -481,10 +508,7 @@ namespace Bit.iOS.Extension
vm.CloseAction = () => CompleteRequest(null, null); vm.CloseAction = () => CompleteRequest(null, null);
} }
var navigationPage = new NavigationPage(homePage); NavigateToPage(homePage);
var loginController = navigationPage.ToUIViewController(MauiContextSingleton.Instance.MauiContext);
loginController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
PresentViewController(loginController, true, null);
LogoutIfAuthed(); LogoutIfAuthed();
} }
@ -501,10 +525,7 @@ namespace Bit.iOS.Extension
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage()); vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage());
} }
var navigationPage = new NavigationPage(environmentPage); NavigateToPage(environmentPage);
var loginController = navigationPage.ToUIViewController(MauiContextSingleton.Instance.MauiContext);
loginController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
PresentViewController(loginController, true, null);
} }
private void LaunchRegisterFlow() private void LaunchRegisterFlow()
@ -519,10 +540,7 @@ namespace Bit.iOS.Extension
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage()); vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage());
} }
var navigationPage = new NavigationPage(registerPage); NavigateToPage(registerPage);
var loginController = navigationPage.ToUIViewController(MauiContextSingleton.Instance.MauiContext);
loginController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
PresentViewController(loginController, true, null);
} }
private void LaunchLoginFlow(string email = null) private void LaunchLoginFlow(string email = null)
@ -542,10 +560,7 @@ namespace Bit.iOS.Extension
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage()); vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage());
} }
var navigationPage = new NavigationPage(loginPage); NavigateToPage(loginPage);
var loginController = navigationPage.ToUIViewController(MauiContextSingleton.Instance.MauiContext);
loginController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
PresentViewController(loginController, true, null);
LogoutIfAuthed(); LogoutIfAuthed();
} }
@ -565,10 +580,7 @@ namespace Bit.iOS.Extension
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage()); vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage());
} }
var navigationPage = new NavigationPage(loginWithDevicePage); NavigateToPage(loginWithDevicePage);
var loginController = navigationPage.ToUIViewController(MauiContextSingleton.Instance.MauiContext);
loginController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
PresentViewController(loginController, true, null);
LogoutIfAuthed(); LogoutIfAuthed();
} }
@ -589,10 +601,7 @@ namespace Bit.iOS.Extension
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage()); vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage());
} }
var navigationPage = new NavigationPage(loginPage); NavigateToPage(loginPage);
var loginController = navigationPage.ToUIViewController(MauiContextSingleton.Instance.MauiContext);
loginController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
PresentViewController(loginController, true, null);
LogoutIfAuthed(); LogoutIfAuthed();
} }
@ -619,10 +628,7 @@ namespace Bit.iOS.Extension
vm.UpdateTempPasswordAction = () => DismissViewController(false, () => LaunchUpdateTempPasswordFlow()); vm.UpdateTempPasswordAction = () => DismissViewController(false, () => LaunchUpdateTempPasswordFlow());
} }
var navigationPage = new NavigationPage(twoFactorPage); NavigateToPage(twoFactorPage);
var twoFactorController = navigationPage.ToUIViewController(MauiContextSingleton.Instance.MauiContext);
twoFactorController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
PresentViewController(twoFactorController, true, null);
} }
private void LaunchSetPasswordFlow() private void LaunchSetPasswordFlow()
@ -638,10 +644,7 @@ namespace Bit.iOS.Extension
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage()); vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage());
} }
var navigationPage = new NavigationPage(setPasswordPage); NavigateToPage(setPasswordPage);
var setPasswordController = navigationPage.ToUIViewController(MauiContextSingleton.Instance.MauiContext);
setPasswordController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
PresentViewController(setPasswordController, true, null);
} }
private void LaunchUpdateTempPasswordFlow() private void LaunchUpdateTempPasswordFlow()
@ -656,10 +659,7 @@ namespace Bit.iOS.Extension
vm.LogOutAction = () => DismissViewController(false, () => LaunchHomePage()); vm.LogOutAction = () => DismissViewController(false, () => LaunchHomePage());
} }
var navigationPage = new NavigationPage(updateTempPasswordPage); NavigateToPage(updateTempPasswordPage);
var updateTempPasswordController = navigationPage.ToUIViewController(MauiContextSingleton.Instance.MauiContext);
updateTempPasswordController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
PresentViewController(updateTempPasswordController, true, null);
} }
private void LaunchDeviceApprovalOptionsFlow() private void LaunchDeviceApprovalOptionsFlow()
@ -675,10 +675,7 @@ namespace Bit.iOS.Extension
vm.LogInWithDeviceAction = () => DismissViewController(false, () => LaunchLoginWithDevice(AuthRequestType.AuthenticateAndUnlock, vm.Email, true)); vm.LogInWithDeviceAction = () => DismissViewController(false, () => LaunchLoginWithDevice(AuthRequestType.AuthenticateAndUnlock, vm.Email, true));
} }
var navigationPage = new NavigationPage(loginApproveDevicePage); NavigateToPage(loginApproveDevicePage);
var loginApproveDeviceController = navigationPage.ToUIViewController(MauiContextSingleton.Instance.MauiContext);
loginApproveDeviceController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
PresentViewController(loginApproveDeviceController, true, null);
} }
} }
} }

View File

@ -10,6 +10,8 @@
<EnableDefaultCompileItems>False</EnableDefaultCompileItems> <EnableDefaultCompileItems>False</EnableDefaultCompileItems>
<DefineConstants>$(DefineConstants);ENABLED_TAP_GESTURE_RECOGNIZER_MAUI_EMBEDDED_WORKAROUND</DefineConstants>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion>
<RootNamespace>Bit.iOS.Extension</RootNamespace> <RootNamespace>Bit.iOS.Extension</RootNamespace>
</PropertyGroup> </PropertyGroup>
@ -70,6 +72,7 @@
</Compile> </Compile>
<BundleResource Include="Resources\MaterialIcons_Regular.ttf" /> <BundleResource Include="Resources\MaterialIcons_Regular.ttf" />
<BundleResource Include="Resources\bwi-font.ttf" /> <BundleResource Include="Resources\bwi-font.ttf" />
<Compile Include="LoadingViewController.TapGestureHack.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Core\Core.csproj" /> <ProjectReference Include="..\Core\Core.csproj" />

View File

@ -0,0 +1,22 @@
#if ENABLED_TAP_GESTURE_RECOGNIZER_MAUI_EMBEDDED_WORKAROUND
using Bit.iOS.Core.Utilities;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using UIKit;
namespace Bit.iOS.ShareExtension
{
public partial class LoadingViewController : UIViewController
{
private void NavigateToPage(ContentPage page)
{
var navigationPage = new NavigationPage(page);
var window = new Window(navigationPage);
window.ToHandler(MauiContextSingleton.Instance.MauiContext);
}
}
}
#endif

View File

@ -137,6 +137,23 @@ namespace Bit.iOS.ShareExtension
} }
} }
#if !ENABLED_TAP_GESTURE_RECOGNIZER_MAUI_EMBEDDED_WORKAROUND
private void NavigateToPage(ContentPage page)
{
var navigationPage = new NavigationPage(page);
var window = new Window(navigationPage);
window.ToHandler(MauiContextSingleton.Instance.MauiContext);
_currentModalController = navigationPage.ToUIViewController(MauiContextSingleton.Instance.MauiContext);
_currentModalController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
_presentingOnNavigationPage = true;
PresentViewController(_currentModalController, true, null);
}
#endif
public void DismissLockAndContinue() public void DismissLockAndContinue()
{ {
Debug.WriteLine("BW Log, Dismissing lock controller."); Debug.WriteLine("BW Log, Dismissing lock controller.");
@ -197,19 +214,6 @@ namespace Bit.iOS.ShareExtension
NavigateToPage(sendPage); NavigateToPage(sendPage);
} }
private void NavigateToPage(ContentPage page)
{
var navigationPage = new NavigationPage(page);
var window = new Window(navigationPage);
window.ToHandler(MauiContextSingleton.Instance.MauiContext);
_currentModalController = navigationPage.ToUIViewController(MauiContextSingleton.Instance.MauiContext);
_currentModalController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
_presentingOnNavigationPage = true;
PresentViewController(_currentModalController, true, null);
}
private async Task<(string, byte[])> LoadDataBytesAsync() private async Task<(string, byte[])> LoadDataBytesAsync()
{ {
var itemProvider = ExtensionContext?.InputItems.FirstOrDefault()?.Attachments?.FirstOrDefault(); var itemProvider = ExtensionContext?.InputItems.FirstOrDefault()?.Attachments?.FirstOrDefault();

View File

@ -10,6 +10,8 @@
<EnableDefaultCompileItems>False</EnableDefaultCompileItems> <EnableDefaultCompileItems>False</EnableDefaultCompileItems>
<DefineConstants>$(DefineConstants);ENABLED_TAP_GESTURE_RECOGNIZER_MAUI_EMBEDDED_WORKAROUND</DefineConstants>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion>
<RootNamespace>Bit.iOS.ShareExtension</RootNamespace> <RootNamespace>Bit.iOS.ShareExtension</RootNamespace>
</PropertyGroup> </PropertyGroup>
@ -62,6 +64,7 @@
<Compile Include="ExtensionNavigationController.designer.cs"> <Compile Include="ExtensionNavigationController.designer.cs">
<DependentUpon>ExtensionNavigationController.cs</DependentUpon> <DependentUpon>ExtensionNavigationController.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="LoadingViewController.TapGestureHack.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<BundleResource Include="..\iOS\Resources\logo_white%403x.png"> <BundleResource Include="..\iOS\Resources\logo_white%403x.png">