Introduce preference options to control the behavior when autofilling TOTP entries (show entry notification, activate keyboard, copy TOTP to clipboard)

Required a bit of refactoring to decide when to bring up keyboard selection dialog. Also changed the code so it shows e.g. on Pixel 6a with Android 14, previously did not.
closes #2308
closes #1286 as it now shows up the entry notificaton (unless disabled) and solves the underlying issue in the best found way
This commit is contained in:
Philipp Crocoll
2024-01-04 19:06:49 +01:00
parent 5edc070aa8
commit 059280efd0
11 changed files with 212 additions and 96 deletions

View File

@@ -140,7 +140,7 @@ namespace keepass2android
//will return the results later
Intent i = new Intent(this, typeof (SelectCurrentDbActivity));
//don't show user notifications when an entry is opened.
var task = new SearchUrlTask() {UrlToSearchFor = _requestedUrl, ShowUserNotifications = ShowUserNotificationsMode.WhenTotp};
var task = new SearchUrlTask() {UrlToSearchFor = _requestedUrl, ShowUserNotifications = ActivationCondition.WhenTotp, ActivateKeyboard = ActivationCondition.Never };
task.ToIntent(i);
StartActivityForResult(i, RequestCodeQuery);
_startedQuery = true;

View File

@@ -47,6 +47,7 @@
<string name="oi_filemanager_web">https://openintents.googlecode.com/files/FileManager-2.0.2.apk</string>
<string name="permission_desc2">KP2A Search</string>
<string name="permission_desc3">KP2A Choose autofill dataset</string>
<string name="AutoFillTotp_prefs_screen_key">AutoFillTotp_prefs_screen_key</string>
<!-- Preference settings -->

View File

@@ -402,6 +402,16 @@
<string name="ShowSeparateNotifications_summary">Show separate notifications for copying username and password to clipboard and activating the keyboard.</string>
<string name="AccServiceAutoFill_prefs">AutoFill Accessibility-Service</string>
<string name="AutoFill_prefs">AutoFill Service</string>
<string name="AutoFillTotp_prefs_ShowNotification_summary">When autofilling an entry with TOTP, show the entry notification with a Copy TOTP button</string>
<string name="AutoFillTotp_prefs_ShowNotification_title">Show entry notification</string>
<string name="AutoFillTotp_prefs_title">Autofill for TOTP entries</string>
<string name="AutoFillTotp_prefs_CopyTotpToClipboard_title">Copy TOTP to clipboard</string>
<string name="AutoFillTotp_prefs_CopyTotpToClipboard_summary">When autofilling an entry with TOTP, copy the TOTP to the clipboard</string>
<string name="AutoFillTotp_prefs_ActivateKeyboard_summary">When autofilling an entry with TOTP, activate the built-in keyboard. The keyboard has a TOTP button.</string>
<string name="AutoFillTotp_prefs_ActivateKeyboard_title">Activate built-in keyboard</string>
<string name="TotpCopiedToClipboard">Copied TOTP to clipboard</string>
<string name="ShowKp2aKeyboardNotification_title">KP2A keyboard notification</string>
<string name="ShowKp2aKeyboardNotification_summary">Make full entry accessible through the KP2A keyboard (recommended).</string>
<string name="OpenKp2aKeyboardAutomatically_title">Switch keyboard</string>

View File

@@ -461,7 +461,8 @@
android:defaultValue="false"
android:title="@string/LogAutofillView_title"
android:key="@string/LogAutofillView_key" />
<CheckBoxPreference
android:enabled="true"
@@ -476,6 +477,38 @@
android:summary="@string/AutofillDisabledQueriesPreference_summary"
android:persistent="false"
android:key="AutofillDisabledQueriesPreference_key"/>
<PreferenceScreen
android:key="@string/AutoFillTotp_prefs_screen_key"
android:title="@string/AutoFillTotp_prefs_title"
>
<keepass2android.ToolbarPreference
android:key="@string/AutoFillTotp_prefs_screen_key"
android:title="@string/AutoFillTotp_prefs_title" />
<CheckBoxPreference android:key="AutoFillTotp_prefs_ShowNotification_key"
android:enabled="true"
android:persistent="true"
android:summary="@string/AutoFillTotp_prefs_ShowNotification_summary"
android:defaultValue="true"
android:title="@string/AutoFillTotp_prefs_ShowNotification_title"
/>
<CheckBoxPreference android:key="AutoFillTotp_prefs_CopyTotpToClipboard_key"
android:enabled="true"
android:persistent="true"
android:summary="@string/AutoFillTotp_prefs_CopyTotpToClipboard_summary"
android:defaultValue="true"
android:title="@string/AutoFillTotp_prefs_CopyTotpToClipboard_title"
/>
<CheckBoxPreference android:key="AutoFillTotp_prefs_ActivateKeyboard_key"
android:enabled="true"
android:persistent="true"
android:summary="@string/AutoFillTotp_prefs_ActivateKeyboard_summary"
android:defaultValue="false"
android:title="@string/AutoFillTotp_prefs_ActivateKeyboard_title"
/>
</PreferenceScreen>
</PreferenceScreen>

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
@@ -306,7 +307,27 @@ namespace keepass2android
}
else if (Intent.Action == Intent.ActionSend)
{
AppTask = new SearchUrlTask { UrlToSearchFor = Intent.GetStringExtra(Intent.ExtraText) };
ActivationCondition activationCondition = ActivationCondition.Never;
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this);
if (prefs.GetBoolean("kp2a_switch_rooted", false))
{
activationCondition = ActivationCondition.Always;
}
else
{
//if the app is about to be closed again (e.g. after searching for a URL and returning to the browser:
// automatically bring up the Keyboard selection dialog
if (prefs.GetBoolean(this.GetString(Resource.String.OpenKp2aKeyboardAutomatically_key), this.Resources.GetBoolean(Resource.Boolean.OpenKp2aKeyboardAutomatically_default)))
{
activationCondition = ActivationCondition.Always;
}
}
AppTask = new SearchUrlTask()
{
UrlToSearchFor = Intent.GetStringExtra(Intent.ExtraText),
ActivateKeyboard = activationCondition
};
}
}

View File

@@ -82,20 +82,15 @@ namespace keepass2android
//if user presses back to leave this activity:
SetResult(Result.Canceled);
UpdateBottomBarElementVisibility(Resource.Id.select_other_entry, true);
UpdateBottomBarElementVisibility(Resource.Id.add_url_entry, true);
if (App.Kp2a.DatabaseIsUnlocked)
{
Query();
Query();
}
// else: LockCloseListActivity.OnResume will trigger a broadcast (LockDatabase) which will cause the activity to be finished.
}
protected override void OnSaveInstanceState(Bundle outState)
@@ -162,9 +157,17 @@ namespace keepass2android
String searchUrl = searchUrlTask.UrlToSearchFor;
selectOtherEntry.Visibility = ViewStates.Visible;
var newTask = new SearchUrlTask() { AutoReturnFromQuery = false, UrlToSearchFor = searchUrl };
SearchUrlTask newTask;
if (AppTask is SelectEntryTask currentSelectTask)
{
newTask = new SearchUrlTask() { AutoReturnFromQuery = false, UrlToSearchFor = searchUrl, ActivateKeyboard = currentSelectTask.ActivateKeyboard };
newTask.ShowUserNotifications = currentSelectTask.ShowUserNotifications;
newTask.ActivateKeyboard = currentSelectTask.ActivateKeyboard;
newTask.CopyTotpToClipboard = currentSelectTask.CopyTotpToClipboard;
}
else
newTask = new SearchUrlTask() { AutoReturnFromQuery = false, UrlToSearchFor = searchUrl, ActivateKeyboard = ActivationCondition.Never };
selectOtherEntry.Click += (sender, e) => {
GroupActivity.Launch(this, newTask, new ActivityLaunchModeRequestCode(0));
@@ -179,7 +182,7 @@ namespace keepass2android
createUrlEntry.Visibility = ViewStates.Visible;
createUrlEntry.Click += (sender, e) =>
{
GroupActivity.Launch(this, new CreateEntryThenCloseTask { Url = searchUrl, ShowUserNotifications = (AppTask as SelectEntryTask)?.ShowUserNotifications ?? ShowUserNotificationsMode.Always }, new ActivityLaunchModeRequestCode(0));
GroupActivity.Launch(this, new CreateEntryThenCloseTask { Url = searchUrl, ShowUserNotifications = (AppTask as SelectEntryTask)?.ShowUserNotifications ?? ActivationCondition.Always }, new ActivityLaunchModeRequestCode(0));
Toast.MakeText(this, GetString(Resource.String.select_group_then_add, new Java.Lang.Object[] { GetString(Resource.String.add_entry) }), ToastLength.Long).Show();
};
}

View File

@@ -10,8 +10,9 @@ namespace keepass2android
{
class Kp2aTotp
{
public const string TotpKey = "TOTP";
readonly ITotpPluginAdapter[] _pluginAdapters = new ITotpPluginAdapter[]
readonly ITotpPluginAdapter[] _pluginAdapters = new ITotpPluginAdapter[]
{
new TrayTotpPluginAdapter(),
new KeeOtpPluginAdapter(),

View File

@@ -13,7 +13,7 @@ namespace PluginTOTP
{
class UpdateTotpTimerTask: TimerTask
{
public const string TotpKey = "TOTP";
public const string TotpKey = Kp2aTotp.TotpKey;
private readonly Context _context;
private readonly ITotpPluginAdapter _adapter;

View File

@@ -10,6 +10,9 @@ using System.Threading;
using KeePassLib;
using KeePassLib.Security;
using KeePassLib.Utility;
using KeeTrayTOTP.Libraries;
using Android.Content.Res;
using Android.Preferences;
namespace keepass2android
{
@@ -342,7 +345,15 @@ namespace keepass2android
public virtual void CompleteOnCreateEntryActivity(EntryActivity activity, Thread notifyPluginsOnOpenThread)
{
activity.StartNotificationsService(false);
//this default implementation is executed when we're opening an entry manually, i.e. without search/autofill.
//We only activate the keyboard if this is enabled in "silent mode"
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(activity);
bool activateKeyboard = prefs.GetBoolean("kp2a_switch_rooted", false) &&
!prefs.GetBoolean(
activity.GetString(Resource.String
.OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key), false);
activity.StartNotificationsService(activateKeyboard);
}
public virtual void PopulatePasswordAccessServiceIntent(Intent intent)
@@ -354,7 +365,8 @@ namespace keepass2android
protected static bool GetBoolFromBundle(Bundle b, string key, bool defaultValue)
{
bool boolValue;
if (!Boolean.TryParse(b.GetString(key), out boolValue))
string stringValue = b.GetString(key);
if (!Boolean.TryParse(stringValue, out boolValue))
{
boolValue = defaultValue;
}
@@ -364,7 +376,8 @@ namespace keepass2android
protected static int GetIntFromBundle(Bundle b, string key, int defaultValue)
{
int intValue;
if (!Int32.TryParse(b.GetString(key), out intValue))
var strValue = b.GetString(key);
if (!Int32.TryParse(strValue, out intValue))
{
intValue = defaultValue;
}
@@ -384,7 +397,7 @@ namespace keepass2android
/// User is about to search an entry for a given URL
/// </summary>
/// Derive from SelectEntryTask. This means that as soon as an Entry is opened, we're returning with
/// ExitAfterTaskComplete. This also allows te specify the flag if we need to display the user notifications.
/// ExitAfterTaskComplete. This also allows to specify the flag if we need to display the user notifications.
public class SearchUrlTask: SelectEntryTask
{
public SearchUrlTask()
@@ -393,8 +406,9 @@ namespace keepass2android
}
public const String UrlToSearchKey = "UrlToSearch";
public const String AutoReturnFromQueryKey = "AutoReturnFromQuery";
public string UrlToSearchFor
public string UrlToSearchFor
{
get;
set;
@@ -417,7 +431,7 @@ namespace keepass2android
}
}
public const String AutoReturnFromQueryKey = "AutoReturnFromQuery";
public bool AutoReturnFromQuery { get; set; }
@@ -425,15 +439,19 @@ namespace keepass2android
{
if (String.IsNullOrEmpty(UrlToSearchFor))
{
GroupActivity.Launch(act, new SelectEntryTask() { ShowUserNotifications = ShowUserNotifications}, new ActivityLaunchModeRequestCode(0));
GroupActivity.Launch(act, new SelectEntryTask() {
ShowUserNotifications = ShowUserNotifications,
CopyTotpToClipboard = CopyTotpToClipboard,
ActivateKeyboard = ActivateKeyboard
},
new ActivityLaunchModeRequestCode(0));
}
else
{
ShareUrlResults.Launch(act, this, new ActivityLaunchModeRequestCode(0));
}
//removed. this causes an issue in the following workflow:
//removed. this causes an issue in the following workflow:
//When the user wants to find an entry for a URL but has the wrong database open he needs
//to switch to another database. But the Task is removed already the first time when going through PasswordActivity
// (with the wrong db).
@@ -536,7 +554,7 @@ namespace keepass2android
}
public enum ShowUserNotificationsMode
public enum ActivationCondition
{
Never,
WhenTotp,
@@ -549,29 +567,34 @@ namespace keepass2android
{
public SelectEntryTask()
{
ShowUserNotifications = ShowUserNotificationsMode.Always;
ShowUserNotifications = ActivationCondition.Always;
CloseAfterCreate = true;
ActivateKeyboard = true;
ActivateKeyboard = ActivationCondition.Never;
CopyTotpToClipboard = false;
}
public const String ShowUserNotificationsKey = "ShowUserNotifications";
public ShowUserNotificationsMode ShowUserNotifications { get; set; }
public ActivationCondition ShowUserNotifications { get; set; }
public const String CloseAfterCreateKey = "CloseAfterCreate";
public const String ActivateKeyboardKey = "ActivateKeyboard";
public const String CopyTotpToClipboardKey = "CopyTotpToClipboard";
public bool CloseAfterCreate { get; set; }
public bool ActivateKeyboard { get; set; }
public ActivationCondition ActivateKeyboard { get; set; }
public bool CopyTotpToClipboard { get; set; }
public override void Setup(Bundle b)
{
ShowUserNotifications = (ShowUserNotificationsMode) GetIntFromBundle(b, ShowUserNotificationsKey, (int)ShowUserNotificationsMode.Always);
ShowUserNotifications = (ActivationCondition) GetIntFromBundle(b, ShowUserNotificationsKey, (int)ActivationCondition.Always);
CloseAfterCreate = GetBoolFromBundle(b, CloseAfterCreateKey, true);
ActivateKeyboard = GetBoolFromBundle(b, ActivateKeyboardKey, true);
ActivateKeyboard = (ActivationCondition)GetIntFromBundle(b, ActivateKeyboardKey, (int)ActivationCondition.Always);
CopyTotpToClipboard = GetBoolFromBundle(b, CopyTotpToClipboardKey, false);
}
@@ -581,7 +604,8 @@ namespace keepass2android
{
yield return new StringExtra { Key = ShowUserNotificationsKey, Value = ((int)ShowUserNotifications).ToString() };
yield return new StringExtra { Key = CloseAfterCreateKey, Value = CloseAfterCreate.ToString() };
yield return new StringExtra { Key = ActivateKeyboardKey, Value = ActivateKeyboard.ToString() };
yield return new StringExtra { Key = ActivateKeyboardKey, Value = ((int)ActivateKeyboard).ToString() };
yield return new StringExtra { Key = CopyTotpToClipboardKey, Value = CopyTotpToClipboard.ToString() };
}
}
@@ -591,18 +615,43 @@ namespace keepass2android
if (ctx == null)
ctx = LocaleManager.LocalizedAppContext;
if ((ShowUserNotifications == ShowUserNotificationsMode.Always)
|| ((ShowUserNotifications == ShowUserNotificationsMode.WhenTotp) && new Kp2aTotp().TryGetAdapter(new PwEntryOutput(activity.Entry, App.Kp2a.CurrentDb)) != null))
{
//show the notifications
activity.StartNotificationsService(ActivateKeyboard);
}
var pwEntryOutput = new PwEntryOutput(activity.Entry, App.Kp2a.CurrentDb);
var totpPluginAdapter = new Kp2aTotp().TryGetAdapter(pwEntryOutput);
bool isTotpEntry = totpPluginAdapter != null;
bool activateKeyboard = ActivateKeyboard == ActivationCondition.Always || (ActivateKeyboard == ActivationCondition.WhenTotp && isTotpEntry);
if ((ShowUserNotifications == ActivationCondition.Always)
|| ((ShowUserNotifications == ActivationCondition.WhenTotp) && isTotpEntry)
|| activateKeyboard)
{
//show the notifications
activity.StartNotificationsService(activateKeyboard);
}
else
{
//to avoid getting into inconsistent state (LastOpenedEntry and Notifications): clear notifications:
CopyToClipboardService.CancelNotifications(activity);
}
if (CloseAfterCreate)
if (CopyTotpToClipboard && isTotpEntry)
{
Dictionary<string, string> entryFields = pwEntryOutput.OutputStrings.ToDictionary(pair => StrUtil.SafeXmlString(pair.Key), pair => pair.Value.ReadString());
var totpData= totpPluginAdapter.GetTotpData(entryFields, activity, true);
if (totpData.IsTotpEntry)
{
TOTPProvider prov = new TOTPProvider(totpData);
string totp = prov.GenerateByByte(totpData.TotpSecret);
CopyToClipboardService.CopyValueToClipboardWithTimeout(activity, totp, true);
Toast.MakeText(activity, activity.GetString(Resource.String.TotpCopiedToClipboard),
ToastLength.Long).Show();
}
}
if (CloseAfterCreate)
{
//give plugins and TOTP time to do their work:
notifyPluginsOnOpenThread.Join(TimeSpan.FromSeconds(1));
@@ -671,8 +720,8 @@ namespace keepass2android
public class CreateEntryThenCloseTask: AppTask
{
public CreateEntryThenCloseTask()
{
ShowUserNotifications = ShowUserNotificationsMode.Always;
{
ShowUserNotifications = ActivationCondition.Always;
}
public override bool CanActivateSearchViewOnStart
@@ -712,13 +761,13 @@ namespace keepass2android
public IList<string> ProtectedFieldsList { get; set; }
public ShowUserNotificationsMode ShowUserNotifications { get; set; }
public ActivationCondition ShowUserNotifications { get; set; }
public override void Setup(Bundle b)
{
ShowUserNotifications = (ShowUserNotificationsMode)GetIntFromBundle(b,ShowUserNotificationsKey, (int)ShowUserNotificationsMode.Always);
ShowUserNotifications = (ActivationCondition)GetIntFromBundle(b,ShowUserNotificationsKey, (int)ActivationCondition.Always);
Url = b.GetString(UrlKey);
AllFields = b.GetString(AllFieldsKey);
@@ -766,7 +815,7 @@ namespace keepass2android
public override void AfterAddNewEntry(EntryEditActivity entryEditActivity, PwEntry newEntry)
{
EntryActivity.Launch(entryEditActivity, newEntry, -1,
new SelectEntryTask { ShowUserNotifications = this.ShowUserNotifications},
new SelectEntryTask() { ShowUserNotifications = this.ShowUserNotifications, ActivateKeyboard = ActivationCondition.Never },
ActivityFlags.ForwardResult);
//no need to call Finish here, that's done in EntryEditActivity ("closeOrShowError")
}

View File

@@ -501,24 +501,8 @@ namespace keepass2android
if (hasKeyboardDataNow)
{
notBuilder.AddKeyboardAccess();
if (prefs.GetBoolean("kp2a_switch_rooted", false))
{
//switch rooted
bool onlySwitchOnSearch = prefs.GetBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key), false);
if (activateKeyboard || (!onlySwitchOnSearch))
{
ActivateKp2aKeyboard();
}
}
else
{
//if the app is about to be closed again (e.g. after searching for a URL and returning to the browser:
// automatically bring up the Keyboard selection dialog
if ((activateKeyboard) && prefs.GetBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomatically_key), Resources.GetBoolean(Resource.Boolean.OpenKp2aKeyboardAutomatically_default)))
{
ActivateKp2aKeyboard();
}
}
if (activateKeyboard)
ActivateKp2aKeyboard();
}
@@ -548,31 +532,6 @@ namespace keepass2android
}
public void ActivateKeyboardIfAppropriate(bool closeAfterCreate, ISharedPreferences prefs)
{
if (prefs.GetBoolean("kp2a_switch_rooted", false))
{
//switch rooted
bool onlySwitchOnSearch = prefs.GetBoolean(
GetString(Resource.String.OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key), false);
if (closeAfterCreate || (!onlySwitchOnSearch))
{
ActivateKp2aKeyboard();
}
}
else
{
//if the app is about to be closed again (e.g. after searching for a URL and returning to the browser:
// automatically bring up the Keyboard selection dialog
if ((closeAfterCreate) &&
prefs.GetBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomatically_key),
Resources.GetBoolean(Resource.Boolean.OpenKp2aKeyboardAutomatically_default)))
{
ActivateKp2aKeyboard();
}
}
}
private bool ClearNotifications()
{
// Notification Manager
@@ -865,14 +824,9 @@ namespace keepass2android
{
//let's bring up the keyboard switching dialog.
//Unfortunately this no longer works starting with Android 9 if our app is not in foreground.
bool mustUseHelperActivity = false;
if ((int)Build.VERSION.SdkInt >= 28)
{
ActivityManager.RunningAppProcessInfo appProcessInfo = new ActivityManager.RunningAppProcessInfo();
ActivityManager.GetMyMemoryState(appProcessInfo);
//at least on Samsung devices, we always need the helper activity
mustUseHelperActivity = (appProcessInfo.Importance != Importance.Foreground) || (Build.Manufacturer != "Google");
}
//first it seemed to be required for Samsung mostly, but there are use cases where it is required for other devices as well.
//Let's be sure and use the helper activity.
bool mustUseHelperActivity = (int)Build.VERSION.SdkInt >= 28;
if (mustUseHelperActivity)
{
try

View File

@@ -10,6 +10,7 @@ using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using AndroidX.Preference;
using KeePass.Util.Spr;
using keepass2android.services.AutofillBase;
using keepass2android.services.AutofillBase.model;
@@ -26,6 +27,32 @@ namespace keepass2android.services.Kp2aAutofill
Permission = "keepass2android." + AppNames.PackagePart + ".permission.Kp2aChooseAutofill")]
public class ChooseForAutofillActivity : ChooseForAutofillActivityBase
{
public bool ActivateKeyboardWhenTotpPreference
{
get
{
return PreferenceManager.GetDefaultSharedPreferences(this)
.GetBoolean("AutoFillTotp_prefs_ActivateKeyboard_key", false);
}
}
public bool CopyTotpToClipboardPreference
{
get
{
return PreferenceManager.GetDefaultSharedPreferences(this)
.GetBoolean("AutoFillTotp_prefs_CopyTotpToClipboard_key", true);
}
}
public bool ShowNotificationPreference
{
get
{
return PreferenceManager.GetDefaultSharedPreferences(this)
.GetBoolean("AutoFillTotp_prefs_ShowNotification_key", true);
}
}
protected override Intent GetQueryIntent(string requestedUrl, bool autoReturnFromQuery, bool useLastOpenedEntry)
{
if (useLastOpenedEntry && (App.Kp2a.LastOpenedEntry?.SearchUrl == requestedUrl))
@@ -36,16 +63,33 @@ namespace keepass2android.services.Kp2aAutofill
//will return the results later
Intent i = new Intent(this, typeof(SelectCurrentDbActivity));
//don't show user notifications when an entry is opened.
var task = new SearchUrlTask() { UrlToSearchFor = requestedUrl, ShowUserNotifications = ShowUserNotificationsMode.WhenTotp, AutoReturnFromQuery = autoReturnFromQuery, ActivateKeyboard = false };
var task = new SearchUrlTask()
{
UrlToSearchFor = requestedUrl,
AutoReturnFromQuery = autoReturnFromQuery
};
SetTotpDependantActionsOnTask(task);
task.ToIntent(i);
return i;
}
private void SetTotpDependantActionsOnTask(SelectEntryTask task)
{
task.ShowUserNotifications =
ShowNotificationPreference ? ActivationCondition.WhenTotp : ActivationCondition.Never;
task.CopyTotpToClipboard = CopyTotpToClipboardPreference;
task.ActivateKeyboard = ActivateKeyboardWhenTotpPreference
? ActivationCondition.WhenTotp
: ActivationCondition.Never;
}
protected override Intent GetOpenEntryIntent(string entryUuid)
{
Intent i = new Intent(this, typeof(SelectCurrentDbActivity));
//don't show user notifications when an entry is opened.
var task = new OpenSpecificEntryTask() { EntryUuid = entryUuid, ShowUserNotifications = ShowUserNotificationsMode.WhenTotp, ActivateKeyboard = false};
var task = new OpenSpecificEntryTask() { EntryUuid = entryUuid };
SetTotpDependantActionsOnTask(task);
task.ToIntent(i);
return i;
}