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.IO; | ||||
| using System.Net; | ||||
| using System.Threading.Tasks; | ||||
| using Android.Content.PM; | ||||
| using Android.Webkit; | ||||
| using Android.Graphics; | ||||
| @@ -49,7 +50,9 @@ using PluginTOTP; | ||||
| using File = Java.IO.File; | ||||
| using Uri = Android.Net.Uri; | ||||
| using keepass2android.fileselect; | ||||
| using KeeTrayTOTP.Libraries; | ||||
| using Boolean = Java.Lang.Boolean; | ||||
| using Android.Util; | ||||
|  | ||||
| namespace keepass2android | ||||
| { | ||||
| @@ -286,6 +289,8 @@ namespace keepass2android | ||||
| 				extraGroup.AddView(view.View); | ||||
| 			} | ||||
|  | ||||
|             SetPasswordStyle(); | ||||
|  | ||||
| 			//update the Entry output in the App database and notify the CopyToClipboard service | ||||
|  | ||||
| 		    if (App.Kp2a.LastOpenedEntry != null) | ||||
| @@ -665,7 +670,7 @@ namespace keepass2android | ||||
| 			EditModeBase editMode = new DefaultEdit(); | ||||
| 			if (KpEntryTemplatedEdit.IsTemplated(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)) | ||||
| 				{ | ||||
| @@ -841,7 +846,7 @@ namespace keepass2android | ||||
| 		{ | ||||
|             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}; | ||||
| 		    _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_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(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); | ||||
|  | ||||
| 			RegisterTextPopup(FindViewById<RelativeLayout>(Resource.Id.username_container), | ||||
| @@ -962,9 +969,11 @@ namespace keepass2android | ||||
| 				.Add(new GotoUrlMenuItem(this, PwDefs.UrlField)); | ||||
| 			RegisterTextPopup(FindViewById<RelativeLayout>(Resource.Id.password_container), | ||||
| 			                  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)); | ||||
|  | ||||
| 			if (Entry.Expires) | ||||
| @@ -991,6 +1000,40 @@ namespace keepass2android | ||||
|  | ||||
| 			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() | ||||
|         { | ||||
| @@ -1043,7 +1086,7 @@ namespace keepass2android | ||||
| 		} | ||||
| 		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) | ||||
| @@ -1056,7 +1099,12 @@ namespace keepass2android | ||||
| 			popupItems.Add(new CopyToClipboardPopupMenuIcon(this, _stringViews[fieldKey], 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)); | ||||
|             } | ||||
|  | ||||
| @@ -1283,11 +1331,16 @@ namespace keepass2android | ||||
| 			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); | ||||
| 			if (_showPassword.Values.All(x => x)) | ||||
| @@ -1324,7 +1377,9 @@ namespace keepass2android | ||||
| 			ClearCache(); | ||||
| 			base.OnResume(); | ||||
| 			_activityDesign.ReapplyTheme(); | ||||
| 		} | ||||
|             isPaused = false; | ||||
|             Task.Run(UpdateTotpCountdown); | ||||
|         } | ||||
|  | ||||
| 		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> | ||||
|     </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 | ||||
|     android:id="@+id/entryfield_container_comment" | ||||
|             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="ErrorUpdatingChalAuxFile">Error updating OTP auxiliary file!</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_SettingsField_title">TOTP Settings field name</string> | ||||
|   <string name="TrayTotp_SettingsField_summary">Enter the field name of the settings field for TrayTotp here.</string> | ||||
|   | ||||
| @@ -1985,6 +1985,9 @@ | ||||
|   <ItemGroup> | ||||
|     <AndroidResource Include="Resources\drawable-mdpi\ic_storage_pcloudall.png" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <AndroidResource Include="Resources\drawable-xhdpi\ic_entry_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. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Philipp Crocoll
					Philipp Crocoll