Merge pull request #2516 from PhilippC/803--totp-overview
TOTP overview
This commit is contained in:
		| @@ -72,8 +72,9 @@ namespace keepass2android | ||||
|         } | ||||
|  | ||||
| 	    private IDatabaseFormat _databaseFormat = new KdbxDatabaseFormat(KdbxFormat.Default); | ||||
|         private bool? _hasTotpEntries; | ||||
|  | ||||
| 		public bool ReloadRequested { get; set; } | ||||
|         public bool ReloadRequested { get; set; } | ||||
|  | ||||
| 	    public bool DidOpenFileChange() | ||||
| 		{ | ||||
| @@ -104,8 +105,9 @@ namespace keepass2android | ||||
| 		    SearchHelper = new SearchDbHelper(app); | ||||
|  | ||||
| 		    _databaseFormat = databaseFormat; | ||||
|             _hasTotpEntries = null; | ||||
|  | ||||
| 		    CanWrite = databaseFormat.CanWrite && !fileStorage.IsReadOnly(iocInfo); | ||||
|             CanWrite = databaseFormat.CanWrite && !fileStorage.IsReadOnly(iocInfo); | ||||
| 		} | ||||
|  | ||||
| 		/// <summary> | ||||
| @@ -200,8 +202,21 @@ namespace keepass2android | ||||
| 				 | ||||
| 				trans.CommitWrite(); | ||||
| 			} | ||||
| 			 | ||||
| 		} | ||||
|             _hasTotpEntries = null; | ||||
|  | ||||
|         } | ||||
|  | ||||
|         public bool HasTotpEntries | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 if (_hasTotpEntries == null) | ||||
|                 { | ||||
| 					_hasTotpEntries = true; | ||||
|                 } | ||||
|                 return _hasTotpEntries.Value; | ||||
|             } | ||||
|         } | ||||
|  | ||||
| 		private void PopulateGlobals(PwGroup currentGroup, bool checkForDuplicateUuids ) | ||||
| 		{ | ||||
|   | ||||
| @@ -39,6 +39,9 @@ using Android.Support.V4.View; | ||||
| using Android.Views.Autofill; | ||||
| using CursorAdapter = Android.Support.V4.Widget.CursorAdapter; | ||||
| using Object = Java.Lang.Object; | ||||
| using Android.Text; | ||||
| using keepass2android.search; | ||||
| using KeeTrayTOTP.Libraries; | ||||
|  | ||||
| namespace keepass2android | ||||
| { | ||||
| @@ -115,6 +118,8 @@ namespace keepass2android | ||||
|                 FindViewById(Resource.Id.fabAddNewEntry).Visibility = 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); | ||||
| @@ -262,6 +267,7 @@ namespace keepass2android | ||||
|         private bool hasCalledOtherActivity = false; | ||||
|         private IMenuItem searchItem; | ||||
|         private IMenuItem searchItemDummy; | ||||
|         private bool isPaused; | ||||
|  | ||||
|         protected override void OnResume() | ||||
|         { | ||||
| @@ -281,8 +287,39 @@ namespace keepass2android | ||||
|             RefreshIfDirty(); | ||||
|  | ||||
|             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() | ||||
|         { | ||||
| @@ -390,6 +427,13 @@ namespace keepass2android | ||||
|         } | ||||
|  | ||||
|  | ||||
|         protected override void OnPause() | ||||
|         { | ||||
|             base.OnPause(); | ||||
|             isPaused = true; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         private void UpdatePostNotificationsPermissionInfo(bool hideForever=false) | ||||
|         { | ||||
|             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) | ||||
|             { | ||||
|                 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.fabAddNewEntry).Visibility = AddEntryEnabled ? ViewStates.Visible : 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) => | ||||
| @@ -588,6 +653,8 @@ namespace keepass2android | ||||
|                     FindViewById(Resource.Id.fabAddNewGroup).Visibility = ViewStates.Gone; | ||||
|                     FindViewById(Resource.Id.fabAddNewEntry).Visibility = ViewStates.Gone; | ||||
|                     FindViewById(Resource.Id.fabAddNew).Visibility = ViewStates.Visible; | ||||
|                     FindViewById(Resource.Id.fabSearch).Visibility = ViewStates.Visible; | ||||
|                     FindViewById(Resource.Id.fabTotpOverview).Visibility = CanShowTotpFab() ? ViewStates.Visible : ViewStates.Gone; | ||||
|                 }; | ||||
|  | ||||
|  | ||||
| @@ -667,7 +734,12 @@ namespace keepass2android | ||||
|  | ||||
|  | ||||
|         } | ||||
|          | ||||
|  | ||||
|         protected virtual bool CanShowTotpFab() | ||||
|         { | ||||
|             return App.Kp2a.CurrentDb.HasTotpEntries && Group == App.Kp2a.CurrentDb.Root; | ||||
|         } | ||||
|  | ||||
|         private bool IsTimeForInfotext(out string lastInfoText) | ||||
|         { | ||||
|             DateTime lastDisplayTime = new DateTime(_prefs.GetLong("LastInfoTextTime", 0)); | ||||
| @@ -1028,6 +1100,7 @@ namespace keepass2android | ||||
|              | ||||
|                 searchView.Iconified = false; | ||||
|                 AppTask.CanActivateSearchViewOnStart = false; | ||||
|                  | ||||
|              | ||||
|         } | ||||
|  | ||||
| @@ -1067,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) | ||||
|         { | ||||
| @@ -1267,6 +1349,7 @@ namespace keepass2android | ||||
|             FindViewById(Resource.Id.fabAddNewGroup).Visibility = ViewStates.Gone; | ||||
|             FindViewById(Resource.Id.fabAddNewEntry).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.cancel_insert_element, true); | ||||
| @@ -1330,6 +1413,7 @@ namespace keepass2android | ||||
|             } | ||||
|  | ||||
|             ListView.ItemClick += (sender, args) => ((GroupListItemView)args.View).OnClick(); | ||||
|              | ||||
|  | ||||
|             StyleListView(); | ||||
|  | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								src/keepass2android/Resources/drawable-mdpi/ic_fab_search.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/keepass2android/Resources/drawable-mdpi/ic_fab_search.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 9.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/keepass2android/Resources/drawable-mdpi/ic_fab_totp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/keepass2android/Resources/drawable-mdpi/ic_fab_totp.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 8.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/keepass2android/Resources/drawable-xhdpi/ic_fab_search.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/keepass2android/Resources/drawable-xhdpi/ic_fab_search.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 11 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/keepass2android/Resources/drawable-xhdpi/ic_fab_totp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/keepass2android/Resources/drawable-xhdpi/ic_fab_totp.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 6.3 KiB | 
| @@ -61,6 +61,28 @@ | ||||
|         android:layout_width="wrap_content" | ||||
|         android:text="group detail" | ||||
|         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> | ||||
|  | ||||
|   <ImageView android:id="@+id/right_arrow" | ||||
|   | ||||
| @@ -400,5 +400,23 @@ | ||||
|             android:layout_marginRight="16dp" | ||||
|             android:layout_marginBottom="160dp" | ||||
|             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> | ||||
| </RelativeLayout> | ||||
| @@ -227,6 +227,7 @@ | ||||
|     <Compile Include="fileselect\FileSelectActivity.cs" /> | ||||
|     <Compile Include="fileselect\FileDbHelper.cs" /> | ||||
|     <Compile Include="search\SearchProvider.cs" /> | ||||
|     <Compile Include="search\SearchTotpResults.cs" /> | ||||
|     <Compile Include="SelectStorageLocationActivity.cs" /> | ||||
|     <Compile Include="services\AutofillBase\AutofillFieldMetadata.cs" /> | ||||
|     <Compile Include="services\AutofillBase\AutofillFieldMetadataCollection.cs" /> | ||||
| @@ -1988,6 +1989,18 @@ | ||||
|   <ItemGroup> | ||||
|     <AndroidResource Include="Resources\drawable-xhdpi\ic_entry_totp.png" /> | ||||
|   </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" /> | ||||
|   <!-- 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. | ||||
|   | ||||
							
								
								
									
										162
									
								
								src/keepass2android/search/SearchTotpResults.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								src/keepass2android/search/SearchTotpResults.cs
									
									
									
									
									
										Normal 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; } | ||||
|         } | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -26,6 +26,10 @@ using Android.Text; | ||||
| using Android.Text.Style; | ||||
| using Android.Preferences; | ||||
| using KeePass.Util.Spr; | ||||
| using KeeTrayTOTP.Libraries; | ||||
| using PluginTOTP; | ||||
| using Android.Content; | ||||
| using System.ComponentModel; | ||||
|  | ||||
|  | ||||
| namespace keepass2android.view | ||||
| @@ -37,8 +41,11 @@ namespace keepass2android.view | ||||
| 		private readonly TextView _textView; | ||||
| 		private readonly TextView _textviewDetails; | ||||
| 		private readonly TextView _textgroupFullPath; | ||||
|         private readonly ProgressBar _totpCountdown; | ||||
|         private readonly TextView _totpText; | ||||
|         private readonly LinearLayout _totpLayout; | ||||
|  | ||||
| 		private int _pos; | ||||
|         private int _pos; | ||||
|  | ||||
| 		private int? _defaultTextColor; | ||||
|  | ||||
| @@ -82,7 +89,18 @@ namespace keepass2android.view | ||||
| 			_textgroupFullPath = (TextView)ev.FindViewById(Resource.Id.group_detail); | ||||
| 			_textgroupFullPath.TextSize = PrefsUtil.GetListDetailTextSize(groupActivity); | ||||
|  | ||||
| 			_showDetail = PreferenceManager.GetDefaultSharedPreferences(groupActivity).GetBoolean( | ||||
|             _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( | ||||
| 				groupActivity.GetString(Resource.String.ShowUsernameInList_key),  | ||||
| 				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.check_mark).Visibility = ViewStates.Invisible; | ||||
|  | ||||
| 		    Database db = App.Kp2a.FindDatabaseForElement(_entry); | ||||
| 		    _db = App.Kp2a.FindDatabaseForElement(_entry); | ||||
|  | ||||
|             ImageView iv = (ImageView)ev.FindViewById(Resource.Id.icon); | ||||
| 			bool isExpired = pw.Expires && pw.ExpiryTime < DateTime.Now; | ||||
| 			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 | ||||
| 			{ | ||||
| 				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); | ||||
|             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); | ||||
|  | ||||
| 			if (isExpired) | ||||
| @@ -146,7 +164,7 @@ namespace keepass2android.view | ||||
| 				_textView.SetTextColor(new Color((int)_defaultTextColor)); | ||||
|  | ||||
| 			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))) | ||||
| 			{ | ||||
| @@ -173,7 +191,7 @@ namespace keepass2android.view | ||||
| 				String groupDetail = pw.ParentGroup.GetFullPath(); | ||||
| 			    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); | ||||
| @@ -186,7 +204,16 @@ namespace keepass2android.view | ||||
| 				_textgroupFullPath.Visibility = ViewStates.Visible; | ||||
| 			} | ||||
|  | ||||
| 		} | ||||
| 			//try to get totp data | ||||
|             UpdateTotp(); | ||||
|              | ||||
|  | ||||
|             | ||||
|                  | ||||
|  | ||||
|              | ||||
|  | ||||
|         } | ||||
| 		 | ||||
| 		public void ConvertView(PwEntry pw, int pos) | ||||
| 		{ | ||||
| @@ -248,6 +275,42 @@ namespace keepass2android.view | ||||
| 	    { | ||||
| 	        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; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 PhilippC
					PhilippC