mirror of
https://github.com/bitwarden/android.git
synced 2024-12-27 11:28:28 +03:00
PM-3349 Added custom window so that we can always get the current Active Window. This is used to support the Android Autofil and multi-window scenarios.
This commit is contained in:
parent
6d4c706026
commit
b6ff6e34f6
2 changed files with 65 additions and 56 deletions
|
@ -69,12 +69,18 @@ namespace Bit.App
|
|||
CurrentWindow.Page = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Window CurrentWindow { get; private set; }
|
||||
|
||||
private Window _autofillWindow;
|
||||
private Window _mainWindow;
|
||||
/// <summary>
|
||||
/// Find the Current Active Window. There should only be one at any point in Android
|
||||
/// </summary>
|
||||
public static ResumeWindow CurrentWindow
|
||||
{
|
||||
get
|
||||
{
|
||||
return Application.Current.Windows.OfType<ResumeWindow>().FirstOrDefault(w => w.IsActive);
|
||||
}
|
||||
}
|
||||
|
||||
//Allows setting Options from MainActivity before base.OnCreate
|
||||
public void SetOptions(AppOptions appOptions)
|
||||
|
@ -94,64 +100,22 @@ namespace Bit.App
|
|||
return new Window(new NavigationPage()); //No actual page needed. Only used for auto-filling the fields directly (externally)
|
||||
}
|
||||
|
||||
//If there's already an existing autofill window we try to get rid of it, mostly to avoid edge cases scenarios.
|
||||
if (_autofillWindow != null)
|
||||
{
|
||||
CloseWindow(_autofillWindow);
|
||||
}
|
||||
|
||||
//"Internal" Autofill and Uri/Otp/CreateSend. This is where we create the autofill specific Window
|
||||
if (Options != null && (Options.FromAutofillFramework || Options.Uri != null || Options.OtpData != null || Options.CreateSend != null))
|
||||
{
|
||||
_autofillWindow = new Window(new NavigationPage(new AndroidNavigationRedirectPage()));
|
||||
_autofillWindow.Created += WindowOnCreatedOrActivated;
|
||||
_autofillWindow.Activated += WindowOnCreatedOrActivated;
|
||||
_autofillWindow.Stopped += WindowOnStopped;
|
||||
_autofillWindow.Destroying += AutofillWindowOnDestroying;
|
||||
_isResumed = true;
|
||||
return _autofillWindow;
|
||||
_isResumed = true; //Specifically for the Autofill scenario we need to manually set the _isResumed here
|
||||
return new AutoFillWindow(new NavigationPage(new AndroidNavigationRedirectPage()));
|
||||
}
|
||||
|
||||
//If we don't have an existing main window we create it, otherwise we just reuse the one we had.
|
||||
if(_mainWindow == null)
|
||||
//If we have an existing MainAppWindow we can use that one
|
||||
var mainAppWindow = Windows.OfType<MainAppWindow>().FirstOrDefault();
|
||||
if (mainAppWindow != null)
|
||||
{
|
||||
_mainWindow = new Window(new NavigationPage(new HomePage(Options)));
|
||||
_mainWindow.Created += WindowOnCreatedOrActivated;
|
||||
_mainWindow.Activated += WindowOnCreatedOrActivated;
|
||||
_mainWindow.Stopped += WindowOnStopped;
|
||||
_mainWindow.Destroying += MainWindowOnDestroying;
|
||||
mainAppWindow.PendingPage = new NavigationPage(new HomePage(Options));
|
||||
}
|
||||
|
||||
return _mainWindow;
|
||||
}
|
||||
|
||||
private void MainWindowOnDestroying(object sender, EventArgs e)
|
||||
{
|
||||
_mainWindow.Created -= WindowOnCreatedOrActivated;
|
||||
_mainWindow.Activated -= WindowOnCreatedOrActivated;
|
||||
_mainWindow.Stopped -= WindowOnStopped;
|
||||
_mainWindow.Destroying -= AutofillWindowOnDestroying;
|
||||
}
|
||||
|
||||
private void AutofillWindowOnDestroying(object sender, EventArgs e)
|
||||
{
|
||||
_autofillWindow.Created -= WindowOnCreatedOrActivated;
|
||||
_autofillWindow.Activated -= WindowOnCreatedOrActivated;
|
||||
_autofillWindow.Stopped -= WindowOnStopped;
|
||||
_autofillWindow.Destroying -= AutofillWindowOnDestroying;
|
||||
}
|
||||
|
||||
private void WindowOnStopped(object sender, EventArgs e)
|
||||
{
|
||||
CurrentWindow = null;
|
||||
}
|
||||
|
||||
private void WindowOnCreatedOrActivated(object sender, EventArgs e)
|
||||
{
|
||||
if (sender is Window window)
|
||||
{
|
||||
CurrentWindow = window;
|
||||
}
|
||||
//Create new main window
|
||||
return new MainAppWindow(new NavigationPage(new HomePage(Options)));
|
||||
}
|
||||
#elif IOS
|
||||
//iOS doesn't use the CreateWindow override used in Android so we just set the Application.Current.MainPage directly
|
||||
|
@ -589,7 +553,7 @@ namespace Bit.App
|
|||
};
|
||||
_isResumed = true;
|
||||
#if IOS
|
||||
//We only set the MainPage here for iOS as Android is using the CreateWindow override for the initial page.
|
||||
//We only set the MainPage here for iOS. Android is using the CreateWindow override for the initial page.
|
||||
App.MainPage = new NavigationPage(new HomePage(Options));
|
||||
#endif
|
||||
_accountsManager.NavigateOnAccountChangeAsync().FireAndForget();
|
||||
|
|
45
src/Core/ResumeWindow.cs
Normal file
45
src/Core/ResumeWindow.cs
Normal file
|
@ -0,0 +1,45 @@
|
|||
namespace Bit.Core
|
||||
{
|
||||
// This ResumeWindow is used as a Workaround for Android to be able to find the current "IsActive" Window
|
||||
// It also allows setting a "PendingPage" on an existing Window which then navigates when the Window is active.
|
||||
public class ResumeWindow : Window
|
||||
{
|
||||
public Page PendingPage {get;set;}
|
||||
public bool IsActive { get; set; }
|
||||
|
||||
public ResumeWindow(Page page) : base(page) { }
|
||||
|
||||
/// <summary>
|
||||
/// You need to do this inside OnActivated not OnResumed
|
||||
/// Androids OnResume maps to OnActivated
|
||||
/// Androids OnRestart is what Maps to OnResumed
|
||||
/// I realize this is confusing from the perspective of Android
|
||||
/// https://github.com/dotnet/maui/issues/1720 explains it a bit better
|
||||
/// </summary>
|
||||
protected override void OnActivated()
|
||||
{
|
||||
base.OnActivated();
|
||||
|
||||
if (PendingPage is not null)
|
||||
Page = PendingPage;
|
||||
|
||||
PendingPage = null;
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
protected override void OnDeactivated()
|
||||
{
|
||||
IsActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
public class MainAppWindow : ResumeWindow
|
||||
{
|
||||
public MainAppWindow(Page page) : base(page) { }
|
||||
}
|
||||
|
||||
public class AutoFillWindow : ResumeWindow
|
||||
{
|
||||
public AutoFillWindow(Page page) : base(page){ }
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue