diff --git a/src/keepass2android/GroupBaseActivity.cs b/src/keepass2android/GroupBaseActivity.cs
index c6d70bb4..b4d323c2 100644
--- a/src/keepass2android/GroupBaseActivity.cs
+++ b/src/keepass2android/GroupBaseActivity.cs
@@ -1140,6 +1140,15 @@ namespace keepass2android
public abstract ElementAndDatabaseId FullGroupId { get; }
+ public virtual bool MayPreviewTotp
+ {
+ get
+ {
+ return !PreferenceManager.GetDefaultSharedPreferences(this).GetBoolean(GetString(Resource.String.masktotp_key),
+ Resources.GetBoolean(Resource.Boolean.masktotp_default));
+ }
+ }
+
public override bool OnPrepareOptionsMenu(IMenu menu)
{
diff --git a/src/keepass2android/search/SearchTotpResults.cs b/src/keepass2android/search/SearchTotpResults.cs
new file mode 100644
index 00000000..59395782
--- /dev/null
+++ b/src/keepass2android/search/SearchTotpResults.cs
@@ -0,0 +1,162 @@
+/*
+This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file is based on Keepassdroid, Copyright Brian Pellin.
+
+ Keepass2Android is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Keepass2Android is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Keepass2Android. If not, see .
+ */
+using System;
+using System.Linq;
+using System.Text.RegularExpressions;
+using Android.App;
+using Android.Content;
+using Android.Content.PM;
+using Android.OS;
+using Android.Preferences;
+using Android.Views;
+using Android.Widget;
+using keepass2android.view;
+using KeePassLib;
+
+namespace keepass2android.search
+{
+ ///
+ /// Activity to show search results
+ ///
+ [Activity(Label = "@string/app_name", Theme = "@style/MyTheme_ActionBar", LaunchMode = Android.Content.PM.LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden)]
+ public class SearchTotpResults : GroupBaseActivity
+ {
+
+ public static void Launch(Activity act, AppTask appTask, ActivityFlags? flags = null)
+ {
+ Intent i = new Intent(act, typeof(SearchTotpResults));
+
+
+ if (flags != null)
+ i.SetFlags((ActivityFlags)flags);
+
+ appTask.ToIntent(i);
+ if (flags != null && (((ActivityFlags)flags) | ActivityFlags.ForwardResult) == ActivityFlags.ForwardResult)
+ act.StartActivity(i);
+ else
+ act.StartActivityForResult(i, 0);
+ }
+
+ public override bool MayPreviewTotp
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ protected override void OnCreate (Bundle bundle)
+ {
+ base.OnCreate (bundle);
+
+ if ( IsFinishing ) {
+ return;
+ }
+
+ SetResult(KeePass.ExitNormal);
+
+ // Likely the app has been killed exit the activity
+ if (!App.Kp2a.DatabaseIsUnlocked)
+ {
+ Finish();
+ }
+
+ Group = new PwGroup()
+ {
+ Name = GetString(Resource.String.TOTP)
+ };
+ try
+ {
+ foreach (var db in App.Kp2a.OpenDatabases)
+ {
+ foreach (var entry in db.EntriesById.Values)
+ {
+ var totpData = new Kp2aTotp().TryGetTotpData(new PwEntryOutput(entry, db));
+ if (totpData?.IsTotpEntry == true)
+ Group.AddEntry(entry, false);
+ }
+
+ }
+ }
+ catch (Exception e)
+ {
+ Kp2aLog.LogUnexpectedError(e);
+ Toast.MakeText(this, e.Message, ToastLength.Long).Show();
+ Finish();
+ return;
+ }
+
+ if (Group == null || (!Group.Entries.Any()))
+ {
+ SetContentView(Resource.Layout.group_empty);
+ }
+
+ SetGroupTitle();
+
+ FragmentManager.FindFragmentById(Resource.Id.list_fragment).ListAdapter = new PwGroupListAdapter(this, Group);
+
+ }
+
+ public override bool EntriesBelongToCurrentDatabaseOnly
+ {
+ get { return false; }
+ }
+
+ public override ElementAndDatabaseId FullGroupId
+ {
+ get { return null; }
+ }
+
+
+
+
+
+ public override void OnCreateContextMenu(IContextMenu menu, View v,
+ IContextMenuContextMenuInfo menuInfo)
+ {
+
+ AdapterView.AdapterContextMenuInfo acmi = (AdapterView.AdapterContextMenuInfo) menuInfo;
+ ClickView cv = (ClickView) acmi.TargetView;
+ cv.OnCreateMenu(menu, menuInfo);
+ }
+
+ public override bool OnContextItemSelected(IMenuItem item) {
+ AdapterView.AdapterContextMenuInfo acmi = (AdapterView.AdapterContextMenuInfo)item.MenuInfo;
+ ClickView cv = (ClickView) acmi.TargetView;
+
+ bool result;
+
+ return cv.OnContextItemSelected(item);
+ }
+
+
+ public override bool OnSearchRequested()
+ {
+ Intent i = new Intent(this, typeof(SearchActivity));
+ this.AppTask.ToIntent(i);
+ i.SetFlags(ActivityFlags.ForwardResult);
+ StartActivity(i);
+ return true;
+ }
+
+ public override bool IsSearchResult
+ {
+ get { return true; }
+ }
+ }
+}
+
diff --git a/src/keepass2android/views/PwEntryView.cs b/src/keepass2android/views/PwEntryView.cs
index 177ef1de..fd5489e6 100644
--- a/src/keepass2android/views/PwEntryView.cs
+++ b/src/keepass2android/views/PwEntryView.cs
@@ -28,7 +28,8 @@ using Android.Preferences;
using KeePass.Util.Spr;
using KeeTrayTOTP.Libraries;
using PluginTOTP;
-using Microsoft.Graph;
+using Android.Content;
+using System.ComponentModel;
namespace keepass2android.view
@@ -92,6 +93,13 @@ namespace keepass2android.view
_totpText = ev.FindViewById(Resource.Id.totp_text);
_totpLayout = ev.FindViewById(Resource.Id.totp_layout);
+ _totpLayout.LongClick += (sender, args) =>
+ {
+ string totp = UpdateTotp();
+ if (!String.IsNullOrEmpty(totp))
+ CopyToClipboardService.CopyValueToClipboardWithTimeout(_groupActivity, totp, true);
+ };
+
_showDetail = PreferenceManager.GetDefaultSharedPreferences(groupActivity).GetBoolean(
groupActivity.GetString(Resource.String.ShowUsernameInList_key),
Resources.GetBoolean(Resource.Boolean.ShowUsernameInList_default));
@@ -200,16 +208,7 @@ namespace keepass2android.view
UpdateTotp();
- if (_totpData?.IsTotpEntry == true)
- {
- _totpLayout.Visibility = ViewStates.Visible;
-
-
- }
- else
- {
- _totpLayout.Visibility = ViewStates.Gone;
- }
+
@@ -283,14 +282,25 @@ namespace keepass2android.view
private Database _db;
- public void UpdateTotp()
+ public string UpdateTotp()
{
-
- _totpData = new Kp2aTotp().TryGetTotpData(new PwEntryOutput(_entry, _db));
+ ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(_groupActivity);
+ bool showTotpDefault = _groupActivity.MayPreviewTotp;
+
+
+ if (showTotpDefault)
+ _totpData = new Kp2aTotp().TryGetTotpData(new PwEntryOutput(_entry, _db));
+ else
+ _totpData = null;
+
+ if (_totpData?.IsTotpEntry != true)
+ {
+ _totpLayout.Visibility = ViewStates.Gone;
+ return null;
+ }
+
+ _totpLayout.Visibility = ViewStates.Visible;
- if (_totpData == null)
- return;
- Kp2aLog.Log("UpdateTotp");
TOTPProvider prov = new TOTPProvider(_totpData);
string totp = prov.GenerateByByte(_totpData.TotpSecret);
@@ -298,6 +308,8 @@ namespace keepass2android.view
var progressBar = _totpCountdown;
progressBar.Progress = prov.Timer;
progressBar.Max = prov.Duration;
+
+ return totp;
}
}
}