Merge pull request #2516 from PhilippC/803--totp-overview

TOTP overview
This commit is contained in:
PhilippC
2024-01-17 18:34:29 +01:00
committed by GitHub
11 changed files with 393 additions and 16 deletions

View File

@@ -72,6 +72,7 @@ namespace keepass2android
} }
private IDatabaseFormat _databaseFormat = new KdbxDatabaseFormat(KdbxFormat.Default); private IDatabaseFormat _databaseFormat = new KdbxDatabaseFormat(KdbxFormat.Default);
private bool? _hasTotpEntries;
public bool ReloadRequested { get; set; } public bool ReloadRequested { get; set; }
@@ -104,6 +105,7 @@ namespace keepass2android
SearchHelper = new SearchDbHelper(app); SearchHelper = new SearchDbHelper(app);
_databaseFormat = databaseFormat; _databaseFormat = databaseFormat;
_hasTotpEntries = null;
CanWrite = databaseFormat.CanWrite && !fileStorage.IsReadOnly(iocInfo); CanWrite = databaseFormat.CanWrite && !fileStorage.IsReadOnly(iocInfo);
} }
@@ -200,9 +202,22 @@ namespace keepass2android
trans.CommitWrite(); trans.CommitWrite();
} }
_hasTotpEntries = null;
} }
public bool HasTotpEntries
{
get
{
if (_hasTotpEntries == null)
{
_hasTotpEntries = true;
}
return _hasTotpEntries.Value;
}
}
private void PopulateGlobals(PwGroup currentGroup, bool checkForDuplicateUuids ) private void PopulateGlobals(PwGroup currentGroup, bool checkForDuplicateUuids )
{ {

View File

@@ -39,6 +39,9 @@ using Android.Support.V4.View;
using Android.Views.Autofill; using Android.Views.Autofill;
using CursorAdapter = Android.Support.V4.Widget.CursorAdapter; using CursorAdapter = Android.Support.V4.Widget.CursorAdapter;
using Object = Java.Lang.Object; using Object = Java.Lang.Object;
using Android.Text;
using keepass2android.search;
using KeeTrayTOTP.Libraries;
namespace keepass2android namespace keepass2android
{ {
@@ -115,6 +118,8 @@ namespace keepass2android
FindViewById(Resource.Id.fabAddNewEntry).Visibility = ViewStates.Gone; FindViewById(Resource.Id.fabAddNewEntry).Visibility = ViewStates.Gone;
FindViewById(Resource.Id.fabAddNew).Visibility = (showAddGroup || showAddEntry) ? ViewStates.Visible : ViewStates.Gone; FindViewById(Resource.Id.fabAddNew).Visibility = (showAddGroup || showAddEntry) ? ViewStates.Visible : ViewStates.Gone;
FindViewById(Resource.Id.fabSearch).Visibility = (showAddGroup || showAddEntry) ? ViewStates.Visible : ViewStates.Gone;
FindViewById(Resource.Id.fabTotpOverview).Visibility = CanShowTotpFab() ? ViewStates.Visible : ViewStates.Gone;
} }
UpdateBottomBarElementVisibility(Resource.Id.insert_element, false); UpdateBottomBarElementVisibility(Resource.Id.insert_element, false);
@@ -262,6 +267,7 @@ namespace keepass2android
private bool hasCalledOtherActivity = false; private bool hasCalledOtherActivity = false;
private IMenuItem searchItem; private IMenuItem searchItem;
private IMenuItem searchItemDummy; private IMenuItem searchItemDummy;
private bool isPaused;
protected override void OnResume() protected override void OnResume()
{ {
@@ -281,8 +287,39 @@ namespace keepass2android
RefreshIfDirty(); RefreshIfDirty();
SetSearchItemVisibility(); SetSearchItemVisibility();
}
isPaused = false;
System.Threading.Tasks.Task.Run(UpdateTotpCountdown);
}
private async System.Threading.Tasks.Task UpdateTotpCountdown()
{
while (!isPaused )
{
RunOnUiThread(() =>
{
var listView = FragmentManager.FindFragmentById<GroupListFragment>(Resource.Id.list_fragment)
.ListView;
if (listView != null)
{
int count = listView.Count;
for (int i = 0; i < count; i++)
{
var item = listView.GetChildAt(i);
if (item is PwEntryView)
{
var entryView = (PwEntryView)item;
entryView.UpdateTotp();
}
}
}
});
await System.Threading.Tasks.Task.Delay(1000);
}
}
private void UpdateInfotexts() private void UpdateInfotexts()
{ {
@@ -390,6 +427,13 @@ namespace keepass2android
} }
protected override void OnPause()
{
base.OnPause();
isPaused = true;
}
private void UpdatePostNotificationsPermissionInfo(bool hideForever=false) private void UpdatePostNotificationsPermissionInfo(bool hideForever=false)
{ {
const string prefsKey = "DidShowNotificationPermissionInfo"; const string prefsKey = "DidShowNotificationPermissionInfo";
@@ -572,6 +616,25 @@ namespace keepass2android
}; };
} }
if (FindViewById(Resource.Id.fabSearch) != null)
{
FindViewById(Resource.Id.fabSearch).Click += (sender, args) =>
{
if (searchView?.Iconified != false)
ActivateSearchView();
else
searchView.Iconified = true;
};
}
if (FindViewById(Resource.Id.fabTotpOverview) != null)
{
FindViewById(Resource.Id.fabTotpOverview).Click += (sender, args) =>
{
SearchTotpResults.Launch(this, this.AppTask);
};
}
if (FindViewById(Resource.Id.fabCancelAddNew) != null) if (FindViewById(Resource.Id.fabCancelAddNew) != null)
{ {
FindViewById(Resource.Id.fabAddNew).Click += (sender, args) => FindViewById(Resource.Id.fabAddNew).Click += (sender, args) =>
@@ -580,6 +643,8 @@ namespace keepass2android
FindViewById(Resource.Id.fabAddNewGroup).Visibility = AddGroupEnabled ? ViewStates.Visible : ViewStates.Gone; FindViewById(Resource.Id.fabAddNewGroup).Visibility = AddGroupEnabled ? ViewStates.Visible : ViewStates.Gone;
FindViewById(Resource.Id.fabAddNewEntry).Visibility = AddEntryEnabled ? ViewStates.Visible : ViewStates.Gone; FindViewById(Resource.Id.fabAddNewEntry).Visibility = AddEntryEnabled ? ViewStates.Visible : ViewStates.Gone;
FindViewById(Resource.Id.fabAddNew).Visibility = ViewStates.Gone; FindViewById(Resource.Id.fabAddNew).Visibility = ViewStates.Gone;
FindViewById(Resource.Id.fabSearch).Visibility = ViewStates.Gone;
FindViewById(Resource.Id.fabTotpOverview).Visibility = ViewStates.Gone;
}; };
FindViewById(Resource.Id.fabCancelAddNew).Click += (sender, args) => FindViewById(Resource.Id.fabCancelAddNew).Click += (sender, args) =>
@@ -588,6 +653,8 @@ namespace keepass2android
FindViewById(Resource.Id.fabAddNewGroup).Visibility = ViewStates.Gone; FindViewById(Resource.Id.fabAddNewGroup).Visibility = ViewStates.Gone;
FindViewById(Resource.Id.fabAddNewEntry).Visibility = ViewStates.Gone; FindViewById(Resource.Id.fabAddNewEntry).Visibility = ViewStates.Gone;
FindViewById(Resource.Id.fabAddNew).Visibility = ViewStates.Visible; FindViewById(Resource.Id.fabAddNew).Visibility = ViewStates.Visible;
FindViewById(Resource.Id.fabSearch).Visibility = ViewStates.Visible;
FindViewById(Resource.Id.fabTotpOverview).Visibility = CanShowTotpFab() ? ViewStates.Visible : ViewStates.Gone;
}; };
@@ -666,6 +733,11 @@ namespace keepass2android
}
protected virtual bool CanShowTotpFab()
{
return App.Kp2a.CurrentDb.HasTotpEntries && Group == App.Kp2a.CurrentDb.Root;
} }
private bool IsTimeForInfotext(out string lastInfoText) private bool IsTimeForInfotext(out string lastInfoText)
@@ -1029,6 +1101,7 @@ namespace keepass2android
searchView.Iconified = false; searchView.Iconified = false;
AppTask.CanActivateSearchViewOnStart = false; AppTask.CanActivateSearchViewOnStart = false;
} }
private void UpdateOfflineModeMenu() private void UpdateOfflineModeMenu()
@@ -1067,6 +1140,15 @@ namespace keepass2android
public abstract ElementAndDatabaseId FullGroupId { get; } 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) public override bool OnPrepareOptionsMenu(IMenu menu)
{ {
@@ -1267,6 +1349,7 @@ namespace keepass2android
FindViewById(Resource.Id.fabAddNewGroup).Visibility = ViewStates.Gone; FindViewById(Resource.Id.fabAddNewGroup).Visibility = ViewStates.Gone;
FindViewById(Resource.Id.fabAddNewEntry).Visibility = ViewStates.Gone; FindViewById(Resource.Id.fabAddNewEntry).Visibility = ViewStates.Gone;
FindViewById(Resource.Id.fabAddNew).Visibility = ViewStates.Gone; FindViewById(Resource.Id.fabAddNew).Visibility = ViewStates.Gone;
FindViewById(Resource.Id.fabSearch).Visibility = ViewStates.Gone;
UpdateBottomBarElementVisibility(Resource.Id.insert_element, true); UpdateBottomBarElementVisibility(Resource.Id.insert_element, true);
UpdateBottomBarElementVisibility(Resource.Id.cancel_insert_element, true); UpdateBottomBarElementVisibility(Resource.Id.cancel_insert_element, true);
@@ -1331,6 +1414,7 @@ namespace keepass2android
ListView.ItemClick += (sender, args) => ((GroupListItemView)args.View).OnClick(); ListView.ItemClick += (sender, args) => ((GroupListItemView)args.View).OnClick();
StyleListView(); StyleListView();
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@@ -61,6 +61,28 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:text="group detail" android:text="group detail"
style="@style/GroupDetailInSearchResult" /> style="@style/GroupDetailInSearchResult" />
<LinearLayout
android:id="@+id/totp_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/totp_text"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:text=""/>
<ProgressBar
android:id="@+id/TotpCountdownProgressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="30dp" />
</LinearLayout>
</LinearLayout> </LinearLayout>
<ImageView android:id="@+id/right_arrow" <ImageView android:id="@+id/right_arrow"

View File

@@ -400,5 +400,23 @@
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
android:layout_marginBottom="160dp" android:layout_marginBottom="160dp"
android:visibility="gone"/> android:visibility="gone"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fabSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom|right"
android:src="@drawable/ic_fab_search"
android:layout_marginRight="16dp"
android:layout_marginBottom="88dp"
android:visibility="gone"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fabTotpOverview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom|right"
android:src="@drawable/ic_fab_totp"
android:layout_marginRight="16dp"
android:layout_marginBottom="160dp"
android:visibility="gone"/>
</android.support.design.widget.CoordinatorLayout> </android.support.design.widget.CoordinatorLayout>
</RelativeLayout> </RelativeLayout>

View File

@@ -227,6 +227,7 @@
<Compile Include="fileselect\FileSelectActivity.cs" /> <Compile Include="fileselect\FileSelectActivity.cs" />
<Compile Include="fileselect\FileDbHelper.cs" /> <Compile Include="fileselect\FileDbHelper.cs" />
<Compile Include="search\SearchProvider.cs" /> <Compile Include="search\SearchProvider.cs" />
<Compile Include="search\SearchTotpResults.cs" />
<Compile Include="SelectStorageLocationActivity.cs" /> <Compile Include="SelectStorageLocationActivity.cs" />
<Compile Include="services\AutofillBase\AutofillFieldMetadata.cs" /> <Compile Include="services\AutofillBase\AutofillFieldMetadata.cs" />
<Compile Include="services\AutofillBase\AutofillFieldMetadataCollection.cs" /> <Compile Include="services\AutofillBase\AutofillFieldMetadataCollection.cs" />
@@ -1988,6 +1989,18 @@
<ItemGroup> <ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\ic_entry_totp.png" /> <AndroidResource Include="Resources\drawable-xhdpi\ic_entry_totp.png" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-mdpi\ic_fab_search.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\ic_fab_search.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-mdpi\ic_fab_totp.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\ic_fab_totp.png" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" /> <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Activity to show search results
/// </summary>
[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<GroupListFragment>(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; }
}
}
}

View File

@@ -26,6 +26,10 @@ using Android.Text;
using Android.Text.Style; using Android.Text.Style;
using Android.Preferences; using Android.Preferences;
using KeePass.Util.Spr; using KeePass.Util.Spr;
using KeeTrayTOTP.Libraries;
using PluginTOTP;
using Android.Content;
using System.ComponentModel;
namespace keepass2android.view namespace keepass2android.view
@@ -37,6 +41,9 @@ namespace keepass2android.view
private readonly TextView _textView; private readonly TextView _textView;
private readonly TextView _textviewDetails; private readonly TextView _textviewDetails;
private readonly TextView _textgroupFullPath; private readonly TextView _textgroupFullPath;
private readonly ProgressBar _totpCountdown;
private readonly TextView _totpText;
private readonly LinearLayout _totpLayout;
private int _pos; private int _pos;
@@ -82,6 +89,17 @@ namespace keepass2android.view
_textgroupFullPath = (TextView)ev.FindViewById(Resource.Id.group_detail); _textgroupFullPath = (TextView)ev.FindViewById(Resource.Id.group_detail);
_textgroupFullPath.TextSize = PrefsUtil.GetListDetailTextSize(groupActivity); _textgroupFullPath.TextSize = PrefsUtil.GetListDetailTextSize(groupActivity);
_totpCountdown = ev.FindViewById<ProgressBar>(Resource.Id.TotpCountdownProgressBar);
_totpText = ev.FindViewById<TextView>(Resource.Id.totp_text);
_totpLayout = ev.FindViewById<LinearLayout>(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( _showDetail = PreferenceManager.GetDefaultSharedPreferences(groupActivity).GetBoolean(
groupActivity.GetString(Resource.String.ShowUsernameInList_key), groupActivity.GetString(Resource.String.ShowUsernameInList_key),
Resources.GetBoolean(Resource.Boolean.ShowUsernameInList_default)); Resources.GetBoolean(Resource.Boolean.ShowUsernameInList_default));
@@ -112,20 +130,20 @@ namespace keepass2android.view
ev.FindViewById(Resource.Id.icon).Visibility = ViewStates.Visible; ev.FindViewById(Resource.Id.icon).Visibility = ViewStates.Visible;
ev.FindViewById(Resource.Id.check_mark).Visibility = ViewStates.Invisible; ev.FindViewById(Resource.Id.check_mark).Visibility = ViewStates.Invisible;
Database db = App.Kp2a.FindDatabaseForElement(_entry); _db = App.Kp2a.FindDatabaseForElement(_entry);
ImageView iv = (ImageView)ev.FindViewById(Resource.Id.icon); ImageView iv = (ImageView)ev.FindViewById(Resource.Id.icon);
bool isExpired = pw.Expires && pw.ExpiryTime < DateTime.Now; bool isExpired = pw.Expires && pw.ExpiryTime < DateTime.Now;
if (isExpired) if (isExpired)
{ {
db.DrawableFactory.AssignDrawableTo(iv, Context, db.KpDatabase, PwIcon.Expired, PwUuid.Zero, false); _db.DrawableFactory.AssignDrawableTo(iv, Context, _db.KpDatabase, PwIcon.Expired, PwUuid.Zero, false);
} else } else
{ {
db.DrawableFactory.AssignDrawableTo(iv, Context, db.KpDatabase, pw.IconId, pw.CustomIconUuid, false); _db.DrawableFactory.AssignDrawableTo(iv, Context, _db.KpDatabase, pw.IconId, pw.CustomIconUuid, false);
} }
String title = pw.Strings.ReadSafe(PwDefs.TitleField); String title = pw.Strings.ReadSafe(PwDefs.TitleField);
title = SprEngine.Compile(title, new SprContext(_entry, db.KpDatabase, SprCompileFlags.All)); title = SprEngine.Compile(title, new SprContext(_entry, _db.KpDatabase, SprCompileFlags.All));
var str = new SpannableString(title); var str = new SpannableString(title);
if (isExpired) if (isExpired)
@@ -146,7 +164,7 @@ namespace keepass2android.view
_textView.SetTextColor(new Color((int)_defaultTextColor)); _textView.SetTextColor(new Color((int)_defaultTextColor));
String detail = pw.Strings.ReadSafe(PwDefs.UserNameField); String detail = pw.Strings.ReadSafe(PwDefs.UserNameField);
detail = SprEngine.Compile(detail, new SprContext(_entry, db.KpDatabase, SprCompileFlags.All)); detail = SprEngine.Compile(detail, new SprContext(_entry, _db.KpDatabase, SprCompileFlags.All));
if ((_showDetail == false) || (String.IsNullOrEmpty(detail))) if ((_showDetail == false) || (String.IsNullOrEmpty(detail)))
{ {
@@ -173,7 +191,7 @@ namespace keepass2android.view
String groupDetail = pw.ParentGroup.GetFullPath(); String groupDetail = pw.ParentGroup.GetFullPath();
if (App.Kp2a.OpenDatabases.Count() > 1) if (App.Kp2a.OpenDatabases.Count() > 1)
{ {
groupDetail += "(" + App.Kp2a.GetFileStorage(db.Ioc).GetDisplayName(db.Ioc) + ")"; groupDetail += "(" + App.Kp2a.GetFileStorage(_db.Ioc).GetDisplayName(_db.Ioc) + ")";
} }
var strGroupDetail = new SpannableString (groupDetail); var strGroupDetail = new SpannableString (groupDetail);
@@ -186,6 +204,15 @@ namespace keepass2android.view
_textgroupFullPath.Visibility = ViewStates.Visible; _textgroupFullPath.Visibility = ViewStates.Visible;
} }
//try to get totp data
UpdateTotp();
} }
public void ConvertView(PwEntry pw, int pos) public void ConvertView(PwEntry pw, int pos)
@@ -248,6 +275,42 @@ namespace keepass2android.view
{ {
LaunchEntry(); LaunchEntry();
} }
private TotpData _totpData;
private Database _db;
public string UpdateTotp()
{
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;
TOTPProvider prov = new TOTPProvider(_totpData);
string totp = prov.GenerateByByte(_totpData.TotpSecret);
_totpText.Text = totp;
var progressBar = _totpCountdown;
progressBar.Progress = prov.Timer;
progressBar.Max = prov.Duration;
return totp;
}
} }
} }