Improved editing of advanced fields,
display and toggle protected fields like password
This commit is contained in:
		| @@ -63,7 +63,8 @@ namespace keepass2android | ||||
| 		private int _pos; | ||||
|  | ||||
| 		AppTask _appTask; | ||||
| 		 | ||||
| 		private List<TextView> _protectedTextViews; | ||||
|  | ||||
|  | ||||
| 		protected void SetEntryView() { | ||||
| 			SetContentView(Resource.Layout.entry_view); | ||||
| @@ -180,16 +181,15 @@ namespace keepass2android | ||||
| 			} | ||||
| 			bool hasExtraFields = false; | ||||
| 			foreach (var view in from pair in Entry.Strings where !PwDefs.IsStandardField(pair.Key) orderby pair.Key  | ||||
| 								 select CreateEditSection(pair.Key, pair.Value.ReadString())) | ||||
| 								 select CreateEditSection(pair.Key, pair.Value.ReadString(), pair.Value.IsProtected)) | ||||
| 			{ | ||||
| 				//View view = new EntrySection(this, null, key, pair.Value.ReadString()); | ||||
| 				extraGroup.AddView(view); | ||||
| 				hasExtraFields = true; | ||||
| 			} | ||||
| 			FindViewById(Resource.Id.entry_extra_strings_label).Visibility = hasExtraFields ? ViewStates.Visible : ViewStates.Gone; | ||||
| 		} | ||||
|  | ||||
| 		View CreateEditSection(string key, string value) | ||||
| 		View CreateEditSection(string key, string value, bool isProtected) | ||||
| 		{ | ||||
| 			LinearLayout layout = new LinearLayout(this, null) {Orientation = Orientation.Vertical}; | ||||
| 			LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent); | ||||
| @@ -199,19 +199,27 @@ namespace keepass2android | ||||
| 			TextView keyView = (TextView)viewInflated; | ||||
| 			if (key != null) | ||||
| 				keyView.Text = key; | ||||
|  | ||||
| 			 | ||||
| 			layout.AddView(keyView); | ||||
| 			TextView valueView = (TextView)LayoutInflater.Inflate(Resource.Layout.entry_extrastring_value, null); | ||||
| 			if (value != null) | ||||
| 				valueView.Text = value; | ||||
| 			valueView.Typeface = Typeface.Monospace; | ||||
| 			if (isProtected) | ||||
| 				RegisterProtectedTextView(valueView); | ||||
|  | ||||
|  | ||||
| 			if ((int)Build.VERSION.SdkInt >= 11) | ||||
| 				valueView.SetTextIsSelectable(true); | ||||
| 			layout.AddView(valueView); | ||||
| 			return layout; | ||||
| 		} | ||||
| 		 | ||||
|  | ||||
| 		private void RegisterProtectedTextView(TextView protectedTextView) | ||||
| 		{ | ||||
| 			_protectedTextViews.Add(protectedTextView); | ||||
| 		} | ||||
|  | ||||
| 		Android.Net.Uri WriteBinaryToFile(string key, bool writeToCacheDirectory) | ||||
| 		{ | ||||
| 			ProtectedBinary pb = Entry.Binaries.Get(key); | ||||
| @@ -365,6 +373,7 @@ namespace keepass2android | ||||
|  | ||||
| 		protected void FillData(bool trimList) | ||||
| 		{ | ||||
| 			_protectedTextViews = new List<TextView>(); | ||||
| 			ImageView iv = (ImageView)FindViewById(Resource.Id.entry_icon); | ||||
| 			if (iv != null) | ||||
| 			{ | ||||
| @@ -388,7 +397,7 @@ namespace keepass2android | ||||
| 			 | ||||
| 			PopulateText(Resource.Id.entry_url, Resource.Id.entry_url_label, Entry.Strings.ReadSafe(PwDefs.UrlField)); | ||||
| 			PopulateText(Resource.Id.entry_password, Resource.Id.entry_password_label, Entry.Strings.ReadSafe(PwDefs.PasswordField)); | ||||
| 			SetPasswordStyle(); | ||||
| 			RegisterProtectedTextView(FindViewById<TextView>(Resource.Id.entry_password)); | ||||
| 			 | ||||
| 			PopulateText(Resource.Id.entry_created, Resource.Id.entry_created_label, getDateTime(Entry.CreationTime)); | ||||
| 			PopulateText(Resource.Id.entry_modified, Resource.Id.entry_modified_label, getDateTime(Entry.LastModificationTime)); | ||||
| @@ -411,7 +420,7 @@ namespace keepass2android | ||||
|  | ||||
| 			PopulateBinaries(trimList); | ||||
|  | ||||
|  | ||||
| 			SetPasswordStyle(); | ||||
| 		} | ||||
| 		 | ||||
| 		private void PopulateText(int viewId, int headerViewId,int resId) { | ||||
| @@ -498,12 +507,17 @@ namespace keepass2android | ||||
| 		} | ||||
| 		 | ||||
| 		private void SetPasswordStyle() { | ||||
| 			TextView password = (TextView) FindViewById(Resource.Id.entry_password); | ||||
| 			 | ||||
| 			if ( _showPassword ) { | ||||
| 				password.TransformationMethod = null; | ||||
| 			} else { | ||||
| 				password.TransformationMethod = PasswordTransformationMethod.Instance; | ||||
| 			foreach (TextView password in _protectedTextViews) | ||||
| 			{ | ||||
|  | ||||
| 				if (_showPassword) | ||||
| 				{ | ||||
| 					password.TransformationMethod = null; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					password.TransformationMethod = PasswordTransformationMethod.Instance; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		protected override void OnResume() | ||||
|   | ||||
| @@ -17,6 +17,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file | ||||
|  | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using Android.App; | ||||
| using Android.Content; | ||||
| using Android.OS; | ||||
| @@ -444,12 +445,9 @@ namespace keepass2android | ||||
| 				 | ||||
| 				TextView valueView = (TextView)view.FindViewById(Resource.Id.value); | ||||
| 				String value = valueView.Text; | ||||
| 				 | ||||
|  | ||||
| 				bool protect = true; | ||||
| 				ProtectedString initialString = State.EntryInDatabase.Strings.Get(key); | ||||
| 				if (initialString != null) | ||||
| 					protect = initialString.IsProtected; | ||||
|  | ||||
| 				bool protect = ((CheckBox) view.FindViewById(Resource.Id.protection)).Checked; | ||||
| 				entry.Strings.Set(key, new ProtectedString(protect, value)); | ||||
| 			} | ||||
| 			 | ||||
| @@ -648,7 +646,7 @@ namespace keepass2android | ||||
| 			ViewGroup binariesGroup = (ViewGroup)FindViewById(Resource.Id.binaries); | ||||
| 			binariesGroup.RemoveAllViews(); | ||||
| 			RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent); | ||||
| 			foreach (KeyValuePair<string, ProtectedBinary> pair in State.Entry.Binaries) | ||||
| 			foreach (KeyValuePair<string, ProtectedBinary> pair in State.Entry.Binaries.OrderBy(p => p.Key) ) | ||||
| 			{ | ||||
| 				String key = pair.Key; | ||||
| 				Button binaryButton = new Button(this) {Text = key}; | ||||
| @@ -790,10 +788,68 @@ namespace keepass2android | ||||
| 			((TextView)ees.FindViewById(Resource.Id.title)).TextChanged += (sender, e) => State.EntryModified = true; | ||||
| 			((TextView)ees.FindViewById(Resource.Id.value)).Text = pair.Value.ReadString(); | ||||
| 			((TextView)ees.FindViewById(Resource.Id.value)).TextChanged += (sender, e) => State.EntryModified = true; | ||||
| 			ees.FindViewById(Resource.Id.delete).Click += (sender, e) => DeleteAdvancedString((View)sender); | ||||
|  | ||||
| 			((CheckBox)ees.FindViewById(Resource.Id.protection)).Checked = pair.Value.IsProtected; | ||||
| 			 | ||||
| 			//ees.FindViewById(Resource.Id.edit_extra).Click += (sender, e) => DeleteAdvancedString((View)sender); | ||||
| 			ees.FindViewById(Resource.Id.edit_extra).Click += (sender, e) => EditAdvancedString((View)sender); | ||||
| 			return ees; | ||||
| 		} | ||||
| 		 | ||||
|  | ||||
| 		private void EditAdvancedString(View sender) | ||||
| 		{ | ||||
| 			AlertDialog.Builder builder = new AlertDialog.Builder(this); | ||||
| 			View dlgView = LayoutInflater.Inflate(Resource.Layout.edit_extra_string_dialog, null); | ||||
| 			builder.SetView(dlgView); | ||||
| 			builder.SetNegativeButton(Android.Resource.String.Cancel, (o, args) => { }); | ||||
| 			builder.SetPositiveButton(Android.Resource.String.Ok, (o, args) => | ||||
| 				{ | ||||
| 					CopyFieldFromExtraDialog(sender, o, Resource.Id.title); | ||||
| 					CopyFieldFromExtraDialog(sender, o, Resource.Id.value); | ||||
| 					CopyCheckboxFromExtraDialog(sender, o, Resource.Id.protection); | ||||
| 				}); | ||||
| 			Dialog dialog = builder.Create(); | ||||
|  | ||||
| 			//setup delete button: | ||||
| 			var deleteButton = dlgView.FindViewById<Button>(Resource.Id.delete_extra); | ||||
| 			deleteButton.SetCompoundDrawablesWithIntrinsicBounds(Resources.GetDrawable(Android.Resource.Drawable.IcMenuDelete), null, null, null); | ||||
| 			deleteButton.Click += (o, args) => | ||||
| 				{ | ||||
| 					DeleteAdvancedString(sender); | ||||
| 					dialog.Dismiss(); | ||||
| 				}; | ||||
| 			//copy values: | ||||
| 			View ees = (View) sender.Parent; | ||||
| 			dlgView.FindViewById<EditText>(Resource.Id.title).Text = ees.FindViewById<EditText>(Resource.Id.title).Text; | ||||
| 			dlgView.FindViewById<EditText>(Resource.Id.value).Text = ees.FindViewById<EditText>(Resource.Id.value).Text; | ||||
| 			dlgView.FindViewById<CheckBox>(Resource.Id.protection).Checked = ees.FindViewById<CheckBox>(Resource.Id.protection).Checked; | ||||
| 			 | ||||
| 			dialog.Show(); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		private void CopyFieldFromExtraDialog(View eesButton, object dialog, int fieldId) | ||||
| 		{ | ||||
| 			var sourceField = ((Dialog)dialog).FindViewById<EditText>(fieldId); | ||||
| 			var targetField = ((TextView)((View)eesButton.Parent).FindViewById(fieldId)); | ||||
| 			if (sourceField.Text != targetField.Text) | ||||
| 			{ | ||||
| 				targetField.Text = sourceField.Text; | ||||
| 				State.EntryModified = true; | ||||
| 			}	 | ||||
| 		} | ||||
|  | ||||
| 		private void CopyCheckboxFromExtraDialog(View eesButton, object dialog, int fieldId) | ||||
| 		{ | ||||
| 			var sourceField = ((Dialog)dialog).FindViewById<CheckBox>(fieldId); | ||||
| 			var targetField = ((CheckBox)((View)eesButton.Parent).FindViewById(fieldId)); | ||||
| 			if (sourceField.Checked != targetField.Checked) | ||||
| 			{ | ||||
| 				targetField.Checked = sourceField.Checked; | ||||
| 				State.EntryModified = true; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		private void FillData() { | ||||
| 			ImageButton currIconButton = (ImageButton) FindViewById(Resource.Id.icon_button); | ||||
| 			App.Kp2a.GetDb().DrawableFactory.AssignDrawableTo(currIconButton, Resources, App.Kp2a.GetDb().KpDatabase, State.Entry.IconId, State.Entry.CustomIconUuid); | ||||
|   | ||||
							
								
								
									
										978
									
								
								src/keepass2android/Resources/Resource.designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										978
									
								
								src/keepass2android/Resources/Resource.designer.cs
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,35 +0,0 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:orientation="horizontal" | ||||
|     android:layout_width="match_parent" | ||||
|     android:paddingTop="1dip" | ||||
|     android:gravity="center_vertical" | ||||
|     android:layout_height="wrap_content"> | ||||
|     <EditText | ||||
|         android:id="@+id/title" | ||||
|         android:singleLine="true" | ||||
|         android:inputType="text" | ||||
|         android:hint="@string/field_name" | ||||
|         style="@style/TextAppearance_EditEntry_Value" | ||||
|         android:layout_width="0dip" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_weight="2" | ||||
|         android:gravity="top|left" | ||||
|         android:layout_marginRight="0dip" /> | ||||
|     <EditText | ||||
|         android:id="@+id/value" | ||||
|         android:hint="@string/field_value" | ||||
|         android:inputType="textMultiLine" | ||||
|         style="@style/TextAppearance_EditEntry_Value" | ||||
|         android:layout_width="0dip" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_weight="3" | ||||
|         android:gravity="top|left" | ||||
|         android:layout_marginRight="0dip" /> | ||||
|     <ImageButton | ||||
|         android:id="@+id/delete" | ||||
|         style="@style/MinusButton" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:gravity="center_vertical" /> | ||||
| </LinearLayout> | ||||
| @@ -26,10 +26,17 @@ | ||||
|         android:layout_weight="3" | ||||
|         android:gravity="top|left" | ||||
|         android:layout_marginRight="0dip" /> | ||||
|     <ImageButton | ||||
|         android:id="@+id/delete" | ||||
|         style="@style/MinusButton" | ||||
|         android:layout_width="wrap_content" | ||||
| 	<CheckBox | ||||
|         android:id="@+id/protection" | ||||
|         android:layout_width="0dip" | ||||
|         android:layout_height="0dip" | ||||
| 		 android:visibility="gone" | ||||
|         android:text="@string/protection"/> | ||||
|     <Button | ||||
|         android:id="@+id/edit_extra" | ||||
|         android:text="…"  | ||||
| 		android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:gravity="center_vertical" /> | ||||
|         android:gravity="center_vertical" | ||||
| 		android:layout_marginRight="8dip" /> | ||||
| </LinearLayout> | ||||
| @@ -211,9 +211,10 @@ | ||||
|   <string name="error_string_key">A field name is required for each string.</string> | ||||
|   <string name="field_name">Field Name</string> | ||||
|   <string name="field_value">Field value</string> | ||||
|   <string name="protection">Memory Protection</string> | ||||
|   <string name="protection">Protected field</string> | ||||
|   <string name="add_binary">Add file attachment...</string> | ||||
|   <string name="add_extra_string">Add additional string</string> | ||||
|   <string name="delete_extra_string">Delete additional string</string> | ||||
|   <string name="database_loaded_quickunlock_enabled">Database loaded, QuickUnlock enabled.</string> | ||||
|   <string name="credentials_dialog_title">Enter server credentials</string> | ||||
|   <string name="UseFileTransactions_title">File transactions</string> | ||||
| @@ -264,11 +265,9 @@ | ||||
| 		* External changes are detected and merged when saving\n | ||||
| 		* Improved loading performance\n | ||||
| 		* Improved search toolbar with suggestions\n | ||||
| 		? New app logo!\n | ||||
| 		? Added support for .kdbp format for faster loading/saving\n | ||||
| 		? Improved editing of extra strings and hidden display when protected\n | ||||
| 		* Added support for .kdbp format for faster loading/saving\n | ||||
| 		* Improved editing of extra strings and hidden display when protected\n | ||||
| 		Thanks to Alex Vallat for his code contributions!\n | ||||
| 		Thanks to Niki Hüttner (www.close-cut.de) for the new logo!\n | ||||
| 	</string> | ||||
| 		<string name="ChangeLog_0_8_3"><b>Version 0.8.3</b>\n | ||||
| * Username/TAN index displayed in entry list (see settings)\n | ||||
|   | ||||
| @@ -131,7 +131,6 @@ | ||||
|     <Compile Include="services\CopyToClipboardService.cs" /> | ||||
|     <Compile Include="search\SearchActivity.cs" /> | ||||
|     <Compile Include="QuickUnlock.cs" /> | ||||
|     <Compile Include="views\EntryEditSection.cs" /> | ||||
|     <Compile Include="LifecycleDebugActivity.cs" /> | ||||
|     <Compile Include="services\QuickUnlockForegroundService.cs" /> | ||||
|     <Compile Include="AssemblyInfo.cs" /> | ||||
| @@ -172,6 +171,9 @@ | ||||
|     <None Include="Resources\drawable-xhdpi\2_action_about.png"> | ||||
|       <Visible>False</Visible> | ||||
|     </None> | ||||
|     <AndroidResource Include="Resources\layout\edit_extra_string_dialog.xml"> | ||||
|       <SubType>AndroidResource</SubType> | ||||
|     </AndroidResource> | ||||
|     <None Include="settings\RoundsPreference %28Kopie%29.cs"> | ||||
|       <Visible>False</Visible> | ||||
|     </None> | ||||
| @@ -565,7 +567,9 @@ | ||||
|     <AndroidResource Include="Resources\layout\url_credentials.xml" /> | ||||
|     <AndroidResource Include="Resources\drawable\section_header.xml" /> | ||||
|     <AndroidResource Include="Resources\drawable\extra_string_header.xml" /> | ||||
|     <AndroidResource Include="Resources\layout\entry_edit_section.xml" /> | ||||
|     <AndroidResource Include="Resources\layout\entry_edit_section.xml"> | ||||
|       <SubType>Designer</SubType> | ||||
|     </AndroidResource> | ||||
|     <AndroidResource Include="Resources\values-de\strings.xml" /> | ||||
|     <AndroidResource Include="Resources\values-ca\strings.xml" /> | ||||
|     <AndroidResource Include="Resources\values-cs\strings.xml" /> | ||||
| @@ -597,7 +601,6 @@ | ||||
|     <AndroidResource Include="Resources\layout-v14\entry_view.xml" /> | ||||
|     <AndroidResource Include="Resources\layout-v14\entry_edit.xml" /> | ||||
|     <AndroidResource Include="Resources\layout-v14\SaveButton.xml" /> | ||||
|     <AndroidResource Include="Resources\layout-v14\entry_edit_section.xml" /> | ||||
|     <AndroidResource Include="Resources\layout-v14\generate_password.xml" /> | ||||
|     <AndroidResource Include="Resources\layout-v14\icon_picker.xml" /> | ||||
|     <AndroidResource Include="Resources\layout-v14\password.xml" /> | ||||
|   | ||||
| @@ -1,82 +0,0 @@ | ||||
| /* | ||||
| This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll.  | ||||
|  | ||||
|   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 2 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 Android.Content; | ||||
| using Android.Runtime; | ||||
| using Android.Util; | ||||
| using Android.Widget; | ||||
| using KeePassLib.Security; | ||||
|  | ||||
| namespace keepass2android.view | ||||
| { | ||||
| 	public class EntryEditSection : LinearLayout  | ||||
| 	{ | ||||
| 		public event EventHandler ContentChanged; | ||||
|  | ||||
| 		public EntryEditSection (IntPtr javaReference, JniHandleOwnership transfer) | ||||
| 			: base(javaReference, transfer) | ||||
| 		{ | ||||
| 			 | ||||
| 		} | ||||
|  | ||||
| 		public EntryEditSection(Context context, IAttributeSet attrs) : | ||||
| 			base (context, attrs) | ||||
| 		{ | ||||
| 			Initialize(); | ||||
| 		} | ||||
|  | ||||
| 		public EntryEditSection(Context context, IAttributeSet attrs, int defStyle) : | ||||
| 			base (context, attrs, defStyle) | ||||
| 		{ | ||||
| 			Initialize(); | ||||
| 		} | ||||
|  | ||||
| 		private void Initialize() | ||||
| 		{ | ||||
| 		} | ||||
| 				 | ||||
| 		 | ||||
| 		public void SetData(String title, ProtectedString value) | ||||
| 		{ | ||||
| 			SetText(Resource.Id.title, title); | ||||
| 			SetText(Resource.Id.value, value.ReadString()); | ||||
| 			 | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		public ImageButton GetDeleteButton() | ||||
| 		{ | ||||
| 			return (ImageButton)FindViewById(Resource.Id.delete); | ||||
| 		} | ||||
| 		 | ||||
| 		private void SetText(int resId, String str) | ||||
| 		{ | ||||
| 			if (str != null) | ||||
| 			{ | ||||
| 				TextView tv = (TextView)FindViewById(resId); | ||||
| 				tv.Text = str; | ||||
| 				tv.TextChanged += (sender, e) => { | ||||
| 					if (ContentChanged != null) | ||||
| 						ContentChanged(this, new EventArgs()); | ||||
| 				}; | ||||
| 			} | ||||
| 			 | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Philipp Crocoll
					Philipp Crocoll