Merge pull request #2344 from iansw246/master

Hide progress dialogs when user input dialog is showing
This commit is contained in:
PhilippC
2023-11-04 18:23:44 +01:00
committed by GitHub

View File

@@ -111,7 +111,6 @@ namespace keepass2android
public class Kp2aApp: IKp2aApp, ICacheSupervisor public class Kp2aApp: IKp2aApp, ICacheSupervisor
{ {
public void Lock(bool allowQuickUnlock = true, bool lockWasTriggeredByTimeout = false) public void Lock(bool allowQuickUnlock = true, bool lockWasTriggeredByTimeout = false)
{ {
@@ -467,8 +466,11 @@ namespace keepass2android
} }
} }
private readonly HashSet<RealProgressDialog> _activeProgressDialogs = new HashSet<RealProgressDialog>();
private void AskForReload(Activity activity, Action<bool> actionOnResult) // Whether the app is currently showing a dialog that requires user input, like a yesNoCancel dialog
private bool _isShowingUserInputDialog = false;
private void AskForReload(Activity activity, Action<bool> actionOnResult)
{ {
AlertDialog.Builder builder = new AlertDialog.Builder(activity); AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.SetTitle(activity.GetString(Resource.String.AskReloadFile_title)); builder.SetTitle(activity.GetString(Resource.String.AskReloadFile_title));
@@ -489,6 +491,8 @@ namespace keepass2android
actionOnResult(true); actionOnResult(true);
actionOnResult = null; actionOnResult = null;
} }
OnUserInputDialogClose();
}); });
builder.SetNegativeButton(activity.GetString(Android.Resource.String.No), (dlgSender, dlgEvt) => builder.SetNegativeButton(activity.GetString(Android.Resource.String.No), (dlgSender, dlgEvt) =>
@@ -499,8 +503,9 @@ namespace keepass2android
actionOnResult(false); actionOnResult(false);
actionOnResult = null; actionOnResult = null;
} }
});
OnUserInputDialogClose();
});
Dialog dialog = builder.Create(); Dialog dialog = builder.Create();
@@ -516,8 +521,11 @@ namespace keepass2android
actionOnResult(false); actionOnResult(false);
actionOnResult = null; actionOnResult = null;
} }
OnUserInputDialogClose();
})); }));
OnUserInputDialogShow();
dialog.Show(); dialog.Show();
} }
@@ -581,35 +589,59 @@ namespace keepass2android
EventHandler dismissHandler, EventHandler dismissHandler,
Context ctx, string messageSuffix = "") Context ctx, string messageSuffix = "")
{ {
Handler handler = new Handler(Looper.MainLooper); Handler handler = new Handler(Looper.MainLooper);
handler.Post(() => handler.Post(() =>
{ {
AlertDialog.Builder builder = new AlertDialog.Builder(ctx); AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.SetTitle(GetResourceString(titleKey)); builder.SetTitle(GetResourceString(titleKey));
builder.SetMessage(GetResourceString(messageKey)+(messageSuffix != "" ? " " + messageSuffix: "")); builder.SetMessage(GetResourceString(messageKey) + (messageSuffix != "" ? " " + messageSuffix : ""));
string yesText = GetResourceString(yesString); // _____handlerWithShow are wrappers around given handlers to update _isSHowingYesNoCancelDialog
builder.SetPositiveButton(yesText, yesHandler); // and to show progress dialog after yesNoCancel dialog is closed
EventHandler<DialogClickEventArgs> yesHandlerWithShow = (sender, args) =>
{
OnUserInputDialogClose();
yesHandler.Invoke(sender, args);
};
string yesText = GetResourceString(yesString);
builder.SetPositiveButton(yesText, yesHandlerWithShow);
string noText = ""; string noText = "";
if (noHandler != null) if (noHandler != null)
{ {
EventHandler<DialogClickEventArgs> noHandlerWithShow = (sender, args) =>
{
OnUserInputDialogClose();
noHandler.Invoke(sender, args);
};
noText = GetResourceString(noString); noText = GetResourceString(noString);
builder.SetNegativeButton(noText, noHandler); builder.SetNegativeButton(noText, noHandlerWithShow);
} }
string cancelText = ""; string cancelText = "";
if (cancelHandler != null) if (cancelHandler != null)
{ {
EventHandler<DialogClickEventArgs> cancelHandlerWithShow = (sender, args) =>
{
OnUserInputDialogClose();
cancelHandler.Invoke(sender, args);
};
cancelText = ctx.GetString(Android.Resource.String.Cancel); cancelText = ctx.GetString(Android.Resource.String.Cancel);
builder.SetNeutralButton(cancelText, builder.SetNeutralButton(cancelText,
cancelHandler); cancelHandlerWithShow);
} }
AlertDialog dialog = builder.Create(); AlertDialog dialog = builder.Create();
if (dismissHandler != null) if (dismissHandler != null)
dialog.SetOnDismissListener(new Util.DismissListener(() => dismissHandler(dialog, EventArgs.Empty))); {
dialog.SetOnDismissListener(new Util.DismissListener(() => {
OnUserInputDialogClose();
dismissHandler(dialog, EventArgs.Empty);
}));
}
OnUserInputDialogShow();
dialog.Show(); dialog.Show();
if (yesText.Length + noText.Length + cancelText.Length >= 20) if (yesText.Length + noText.Length + cancelText.Length >= 20)
@@ -626,12 +658,53 @@ namespace keepass2android
} }
} }
} }
); );
} }
public Handler UiThreadHandler /// <summary>
/// Shows all non-dismissed progress dialogs.
/// If there are multiple progressDialogs active, they all will be showing.
/// There probably will never be multiple dialogs at the same time because only one ProgressTask can run at a time.
/// Even if multiple dialogs show at the same time, it shouldn't be too much of an issue
/// because they are just progress indicators.
/// </summary>
private void ShowAllActiveProgressDialogs()
{
foreach (RealProgressDialog progressDialog in _activeProgressDialogs)
{
progressDialog.Show();
}
}
private void HideAllActiveProgressDialogs()
{
foreach (RealProgressDialog progressDialog in _activeProgressDialogs)
{
progressDialog.Hide();
}
}
/// <summary>
/// Hide progress dialogs whenever a dialog that requires user interaction
/// appears so that the progress dialogs cannot cover the user-interaction dialog
/// </summary>
private void OnUserInputDialogShow()
{
_isShowingUserInputDialog = true;
HideAllActiveProgressDialogs();
}
/// <summary>
/// Show previously hidden progress dialogs after user interaction with dialog finished
/// </summary>
private void OnUserInputDialogClose()
{
_isShowingUserInputDialog = false;
ShowAllActiveProgressDialogs();
}
public Handler UiThreadHandler
{ {
get { return new Handler(); } get { return new Handler(); }
} }
@@ -642,9 +715,11 @@ namespace keepass2android
private class RealProgressDialog : IProgressDialog private class RealProgressDialog : IProgressDialog
{ {
private readonly ProgressDialog _pd; private readonly ProgressDialog _pd;
private readonly Kp2aApp _app;
public RealProgressDialog(Context ctx) public RealProgressDialog(Context ctx, Kp2aApp app)
{ {
_app = app;
_pd = new ProgressDialog(ctx); _pd = new ProgressDialog(ctx);
_pd.SetCancelable(false); _pd.SetCancelable(false);
} }
@@ -669,18 +744,28 @@ namespace keepass2android
{ {
Kp2aLog.LogUnexpectedError(e); Kp2aLog.LogUnexpectedError(e);
} }
_app._activeProgressDialogs.Remove(this);
} }
public void Show() public void Show()
{ {
_pd.Show(); _app._activeProgressDialogs.Add(this);
// Only show if asking dialog not also showing
if (!_app._isShowingUserInputDialog)
{
_pd.Show();
}
}
public void Hide()
{
_pd.Hide();
} }
} }
public IProgressDialog CreateProgressDialog(Context ctx) public IProgressDialog CreateProgressDialog(Context ctx)
{ {
return new RealProgressDialog(ctx); return new RealProgressDialog(ctx, this);
} }
public IFileStorage GetFileStorage(IOConnectionInfo iocInfo) public IFileStorage GetFileStorage(IOConnectionInfo iocInfo)