move TOTP field up in EntryActivity and add a progress bar to indicate the time left for using the TOTP
closes https://github.com/PhilippC/keepass2android/issues/2315
This commit is contained in:
@@ -32,6 +32,7 @@ using Android.Text.Method;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Android.Content.PM;
|
using Android.Content.PM;
|
||||||
using Android.Webkit;
|
using Android.Webkit;
|
||||||
using Android.Graphics;
|
using Android.Graphics;
|
||||||
@@ -49,7 +50,9 @@ using PluginTOTP;
|
|||||||
using File = Java.IO.File;
|
using File = Java.IO.File;
|
||||||
using Uri = Android.Net.Uri;
|
using Uri = Android.Net.Uri;
|
||||||
using keepass2android.fileselect;
|
using keepass2android.fileselect;
|
||||||
|
using KeeTrayTOTP.Libraries;
|
||||||
using Boolean = Java.Lang.Boolean;
|
using Boolean = Java.Lang.Boolean;
|
||||||
|
using Android.Util;
|
||||||
|
|
||||||
namespace keepass2android
|
namespace keepass2android
|
||||||
{
|
{
|
||||||
@@ -286,6 +289,8 @@ namespace keepass2android
|
|||||||
extraGroup.AddView(view.View);
|
extraGroup.AddView(view.View);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetPasswordStyle();
|
||||||
|
|
||||||
//update the Entry output in the App database and notify the CopyToClipboard service
|
//update the Entry output in the App database and notify the CopyToClipboard service
|
||||||
|
|
||||||
if (App.Kp2a.LastOpenedEntry != null)
|
if (App.Kp2a.LastOpenedEntry != null)
|
||||||
@@ -665,7 +670,7 @@ namespace keepass2android
|
|||||||
EditModeBase editMode = new DefaultEdit();
|
EditModeBase editMode = new DefaultEdit();
|
||||||
if (KpEntryTemplatedEdit.IsTemplated(App.Kp2a.CurrentDb, this.Entry))
|
if (KpEntryTemplatedEdit.IsTemplated(App.Kp2a.CurrentDb, this.Entry))
|
||||||
editMode = new KpEntryTemplatedEdit(App.Kp2a.CurrentDb, this.Entry);
|
editMode = new KpEntryTemplatedEdit(App.Kp2a.CurrentDb, this.Entry);
|
||||||
foreach (var key in editMode.SortExtraFieldKeys(Entry.Strings.GetKeys().Where(key=> !PwDefs.IsStandardField(key))))
|
foreach (var key in editMode.SortExtraFieldKeys(Entry.Strings.GetKeys().Where(key=> !PwDefs.IsStandardField(key) && key != Kp2aTotp.TotpKey)))
|
||||||
{
|
{
|
||||||
if (editMode.IsVisible(key))
|
if (editMode.IsVisible(key))
|
||||||
{
|
{
|
||||||
@@ -841,7 +846,7 @@ namespace keepass2android
|
|||||||
{
|
{
|
||||||
if (!_showPassword.ContainsKey(protectedTextView))
|
if (!_showPassword.ContainsKey(protectedTextView))
|
||||||
{
|
{
|
||||||
_showPassword[protectedTextView] = fieldKey == UpdateTotpTimerTask.TotpKey ? _showTotpDefault : _showPasswordDefault;
|
_showPassword[protectedTextView] = fieldKey == Kp2aTotp.TotpKey ? _showTotpDefault : _showPasswordDefault;
|
||||||
}
|
}
|
||||||
var protectedTextviewGroup = new ProtectedTextviewGroup { ProtectedField = protectedTextView, VisibleProtectedField = visibleTextView};
|
var protectedTextviewGroup = new ProtectedTextviewGroup { ProtectedField = protectedTextView, VisibleProtectedField = visibleTextView};
|
||||||
_protectedTextViews.Add(protectedTextviewGroup);
|
_protectedTextViews.Add(protectedTextviewGroup);
|
||||||
@@ -947,11 +952,13 @@ namespace keepass2android
|
|||||||
|
|
||||||
PopulateStandardText(Resource.Id.entry_user_name, Resource.Id.entryfield_container_username, PwDefs.UserNameField);
|
PopulateStandardText(Resource.Id.entry_user_name, Resource.Id.entryfield_container_username, PwDefs.UserNameField);
|
||||||
PopulateStandardText(Resource.Id.entry_url, Resource.Id.entryfield_container_url, PwDefs.UrlField);
|
PopulateStandardText(Resource.Id.entry_url, Resource.Id.entryfield_container_url, PwDefs.UrlField);
|
||||||
PopulateStandardText(new List<int> { Resource.Id.entry_password, Resource.Id.entry_password_visible}, Resource.Id.entryfield_container_password, PwDefs.PasswordField);
|
PopulateStandardText(new List<int> { Resource.Id.entry_totp, Resource.Id.entry_totp_visible }, Resource.Id.entryfield_container_totp, Kp2aTotp.TotpKey);
|
||||||
|
PopulateStandardText(new List<int> { Resource.Id.entry_password, Resource.Id.entry_password_visible}, Resource.Id.entryfield_container_password, PwDefs.PasswordField);
|
||||||
|
|
||||||
RegisterProtectedTextView(PwDefs.PasswordField, FindViewById<TextView>(Resource.Id.entry_password), FindViewById<TextView>(Resource.Id.entry_password_visible));
|
RegisterProtectedTextView(PwDefs.PasswordField, FindViewById<TextView>(Resource.Id.entry_password), FindViewById<TextView>(Resource.Id.entry_password_visible));
|
||||||
|
RegisterProtectedTextView(Kp2aTotp.TotpKey, FindViewById<TextView>(Resource.Id.entry_totp), FindViewById<TextView>(Resource.Id.entry_totp_visible));
|
||||||
|
|
||||||
RegisterTextPopup(FindViewById<RelativeLayout> (Resource.Id.groupname_container),
|
RegisterTextPopup(FindViewById<RelativeLayout> (Resource.Id.groupname_container),
|
||||||
FindViewById (Resource.Id.entry_group_name), KeyGroupFullPath);
|
FindViewById (Resource.Id.entry_group_name), KeyGroupFullPath);
|
||||||
|
|
||||||
RegisterTextPopup(FindViewById<RelativeLayout>(Resource.Id.username_container),
|
RegisterTextPopup(FindViewById<RelativeLayout>(Resource.Id.username_container),
|
||||||
@@ -962,9 +969,11 @@ namespace keepass2android
|
|||||||
.Add(new GotoUrlMenuItem(this, PwDefs.UrlField));
|
.Add(new GotoUrlMenuItem(this, PwDefs.UrlField));
|
||||||
RegisterTextPopup(FindViewById<RelativeLayout>(Resource.Id.password_container),
|
RegisterTextPopup(FindViewById<RelativeLayout>(Resource.Id.password_container),
|
||||||
FindViewById(Resource.Id.password_vdots), PwDefs.PasswordField);
|
FindViewById(Resource.Id.password_vdots), PwDefs.PasswordField);
|
||||||
|
RegisterTextPopup(FindViewById<RelativeLayout>(Resource.Id.totp_container),
|
||||||
|
FindViewById(Resource.Id.totp_vdots), Kp2aTotp.TotpKey);
|
||||||
|
|
||||||
|
|
||||||
PopulateText(Resource.Id.entry_created, Resource.Id.entryfield_container_created, getDateTime(Entry.CreationTime));
|
PopulateText(Resource.Id.entry_created, Resource.Id.entryfield_container_created, getDateTime(Entry.CreationTime));
|
||||||
PopulateText(Resource.Id.entry_modified, Resource.Id.entryfield_container_modified, getDateTime(Entry.LastModificationTime));
|
PopulateText(Resource.Id.entry_modified, Resource.Id.entryfield_container_modified, getDateTime(Entry.LastModificationTime));
|
||||||
|
|
||||||
if (Entry.Expires)
|
if (Entry.Expires)
|
||||||
@@ -991,6 +1000,40 @@ namespace keepass2android
|
|||||||
|
|
||||||
SetPasswordStyle();
|
SetPasswordStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task UpdateTotpCountdown()
|
||||||
|
{
|
||||||
|
if (App.Kp2a.LastOpenedEntry == null)
|
||||||
|
return;
|
||||||
|
var totpData = new Kp2aTotp().TryGetTotpData(App.Kp2a.LastOpenedEntry);
|
||||||
|
|
||||||
|
if (totpData == null || !totpData.IsTotpEntry)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var totpProvider = new TOTPProvider(totpData);
|
||||||
|
|
||||||
|
var progressBar = FindViewById<ProgressBar>(Resource.Id.TotpCountdownProgressBar);
|
||||||
|
|
||||||
|
int lastSecondsLeft = -1;
|
||||||
|
while (!isPaused && progressBar != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
int secondsLeft = totpProvider.Timer;
|
||||||
|
|
||||||
|
if (secondsLeft != lastSecondsLeft)
|
||||||
|
{
|
||||||
|
lastSecondsLeft = secondsLeft;
|
||||||
|
// Update the progress bar on the UI thread
|
||||||
|
RunOnUiThread(() =>
|
||||||
|
{
|
||||||
|
progressBar.Progress = secondsLeft;
|
||||||
|
progressBar.Max = totpProvider.Duration;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void PopulatePreviousVersions()
|
private void PopulatePreviousVersions()
|
||||||
{
|
{
|
||||||
@@ -1043,7 +1086,7 @@ namespace keepass2android
|
|||||||
}
|
}
|
||||||
private List<IPopupMenuItem> RegisterTextPopup(View container, View anchor, string fieldKey)
|
private List<IPopupMenuItem> RegisterTextPopup(View container, View anchor, string fieldKey)
|
||||||
{
|
{
|
||||||
return RegisterTextPopup(container, anchor, fieldKey, Entry.Strings.GetSafe(fieldKey).IsProtected);
|
return RegisterTextPopup(container, anchor, fieldKey, Entry.Strings.GetSafe(fieldKey).IsProtected || fieldKey == Kp2aTotp.TotpKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<IPopupMenuItem> RegisterTextPopup(View container, View anchor, string fieldKey, bool isProtected)
|
private List<IPopupMenuItem> RegisterTextPopup(View container, View anchor, string fieldKey, bool isProtected)
|
||||||
@@ -1056,7 +1099,12 @@ namespace keepass2android
|
|||||||
popupItems.Add(new CopyToClipboardPopupMenuIcon(this, _stringViews[fieldKey], isProtected));
|
popupItems.Add(new CopyToClipboardPopupMenuIcon(this, _stringViews[fieldKey], isProtected));
|
||||||
if (isProtected)
|
if (isProtected)
|
||||||
{
|
{
|
||||||
var valueView = container.FindViewById<TextView>(fieldKey == PwDefs.PasswordField ? Resource.Id.entry_password : Resource.Id.entry_extra);
|
var valueView = container.FindViewById<TextView>(fieldKey switch
|
||||||
|
{
|
||||||
|
PwDefs.PasswordField => Resource.Id.entry_password,
|
||||||
|
Kp2aTotp.TotpKey => Resource.Id.entry_totp,
|
||||||
|
_ => Resource.Id.entry_extra
|
||||||
|
});
|
||||||
popupItems.Add(new ToggleVisibilityPopupMenuItem(this, valueView));
|
popupItems.Add(new ToggleVisibilityPopupMenuItem(this, valueView));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1283,11 +1331,16 @@ namespace keepass2android
|
|||||||
return base.OnPrepareOptionsMenu(menu);
|
return base.OnPrepareOptionsMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isPaused = false;
|
||||||
|
|
||||||
|
protected override void OnPause()
|
||||||
|
{
|
||||||
|
base.OnPause();
|
||||||
|
isPaused = true;
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateTogglePasswordMenu()
|
|
||||||
|
private void UpdateTogglePasswordMenu()
|
||||||
{
|
{
|
||||||
IMenuItem togglePassword = _menu.FindItem(Resource.Id.menu_toggle_pass);
|
IMenuItem togglePassword = _menu.FindItem(Resource.Id.menu_toggle_pass);
|
||||||
if (_showPassword.Values.All(x => x))
|
if (_showPassword.Values.All(x => x))
|
||||||
@@ -1324,7 +1377,9 @@ namespace keepass2android
|
|||||||
ClearCache();
|
ClearCache();
|
||||||
base.OnResume();
|
base.OnResume();
|
||||||
_activityDesign.ReapplyTheme();
|
_activityDesign.ReapplyTheme();
|
||||||
}
|
isPaused = false;
|
||||||
|
Task.Run(UpdateTotpCountdown);
|
||||||
|
}
|
||||||
|
|
||||||
public void ClearCache()
|
public void ClearCache()
|
||||||
{
|
{
|
||||||
|
|||||||
BIN
src/keepass2android/Resources/drawable-mdpi/ic_entry_totp.png
Normal file
BIN
src/keepass2android/Resources/drawable-mdpi/ic_entry_totp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.8 KiB |
BIN
src/keepass2android/Resources/drawable-xhdpi/ic_entry_totp.png
Normal file
BIN
src/keepass2android/Resources/drawable-xhdpi/ic_entry_totp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.1 KiB |
@@ -184,6 +184,68 @@
|
|||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/entryfield_container_totp"
|
||||||
|
style="@style/EntryEditSingleLine_container">
|
||||||
|
<ImageView
|
||||||
|
style="@style/EntryEditSingleLine_ImageView"
|
||||||
|
android:src="@drawable/ic_entry_totp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
<!-- TOTP -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/entry_totp_label"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/TOTP"
|
||||||
|
style="@style/EntryFieldHeader" />
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/totp_container"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:clickable="true"
|
||||||
|
android:background="?android:attr/selectableItemBackground">
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/totp_vdots"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="15dp"
|
||||||
|
android:src="@drawable/vdots"
|
||||||
|
android:gravity="right|bottom"
|
||||||
|
android:layout_alignParentRight="true" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/entry_totp"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:password="true"
|
||||||
|
android:typeface="monospace"
|
||||||
|
android:layout_toLeftOf="@id/totp_vdots"
|
||||||
|
style="@style/EntryItem" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/entry_totp_visible"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_toLeftOf="@id/totp_vdots"
|
||||||
|
style="@style/EntryItem" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<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
|
<LinearLayout
|
||||||
android:id="@+id/entryfield_container_comment"
|
android:id="@+id/entryfield_container_comment"
|
||||||
style="@style/EntryEditSingleLine_container">
|
style="@style/EntryEditSingleLine_container">
|
||||||
|
|||||||
@@ -599,6 +599,7 @@
|
|||||||
<string name="CouldntLoadChalAuxFile_Hint">Please use the KeeChallenge plugin in KeePass 2.x (PC) to configure your database for use with challenge-response!</string>
|
<string name="CouldntLoadChalAuxFile_Hint">Please use the KeeChallenge plugin in KeePass 2.x (PC) to configure your database for use with challenge-response!</string>
|
||||||
<string name="ErrorUpdatingChalAuxFile">Error updating OTP auxiliary file!</string>
|
<string name="ErrorUpdatingChalAuxFile">Error updating OTP auxiliary file!</string>
|
||||||
<string name="TrayTotp_SeedField_title">TOTP Seed field name</string>
|
<string name="TrayTotp_SeedField_title">TOTP Seed field name</string>
|
||||||
|
<string name="TOTP">TOTP</string>
|
||||||
<string name="TrayTotp_SeedField_summary">If you are using the Keepass 2 plugin "TrayTotp" with non-default settings, enter the field name for the seed field here according to the settings on the PC.</string>
|
<string name="TrayTotp_SeedField_summary">If you are using the Keepass 2 plugin "TrayTotp" with non-default settings, enter the field name for the seed field here according to the settings on the PC.</string>
|
||||||
<string name="TrayTotp_SettingsField_title">TOTP Settings field name</string>
|
<string name="TrayTotp_SettingsField_title">TOTP Settings field name</string>
|
||||||
<string name="TrayTotp_SettingsField_summary">Enter the field name of the settings field for TrayTotp here.</string>
|
<string name="TrayTotp_SettingsField_summary">Enter the field name of the settings field for TrayTotp here.</string>
|
||||||
|
|||||||
@@ -1985,6 +1985,9 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AndroidResource Include="Resources\drawable-mdpi\ic_storage_pcloudall.png" />
|
<AndroidResource Include="Resources\drawable-mdpi\ic_storage_pcloudall.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\drawable-xhdpi\ic_entry_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.
|
||||||
|
|||||||
Reference in New Issue
Block a user