Added support for Entry templates
This commit is contained in:
parent
b1dcc4f7a9
commit
5d8aa8afe0
|
@ -438,11 +438,18 @@ namespace keepass2android
|
|||
{
|
||||
ViewGroup extraGroup = (ViewGroup) FindViewById(Resource.Id.extra_strings);
|
||||
bool hasExtras = false;
|
||||
foreach (var pair in Entry.Strings.Where(pair => !PwDefs.IsStandardField(pair.Key)).OrderBy(pair => pair.Key))
|
||||
IEditMode editMode = new DefaultEdit();
|
||||
if (KpEntryTemplatedEdit.IsTemplated(App.Kp2a.GetDb(), this.Entry))
|
||||
editMode = new KpEntryTemplatedEdit(App.Kp2a.GetDb(), this.Entry);
|
||||
foreach (var key in editMode.SortExtraFieldKeys(Entry.Strings.GetKeys().Where(key=> !PwDefs.IsStandardField(key))))
|
||||
{
|
||||
hasExtras = true;
|
||||
var stringView = CreateExtraSection(pair.Key, pair.Value.ReadString(), pair.Value.IsProtected);
|
||||
extraGroup.AddView(stringView.View);
|
||||
if (editMode.IsVisible(key))
|
||||
{
|
||||
hasExtras = true;
|
||||
var value = Entry.Strings.Get(key);
|
||||
var stringView = CreateExtraSection(key, value.ReadString(), value.IsProtected);
|
||||
extraGroup.AddView(stringView.View);
|
||||
}
|
||||
}
|
||||
FindViewById(Resource.Id.extra_strings_container).Visibility = hasExtras ? ViewStates.Visible : ViewStates.Gone;
|
||||
}
|
||||
|
|
|
@ -33,16 +33,23 @@ using KeePassLib.Security;
|
|||
using Android.Content.PM;
|
||||
using System.IO;
|
||||
using System.Globalization;
|
||||
using Android.Graphics;
|
||||
using Android.Util;
|
||||
using Debug = System.Diagnostics.Debug;
|
||||
using File = System.IO.File;
|
||||
using Object = Java.Lang.Object;
|
||||
using Uri = Android.Net.Uri;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
[Activity(Label = "@string/app_name", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden, Theme = "@style/MyTheme_ActionBar")]
|
||||
[Activity(Label = "@string/app_name", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden, Theme = "@style/MyTheme_ActionBar")]
|
||||
public class EntryEditActivity : LockCloseActivity {
|
||||
|
||||
|
||||
|
||||
public const String KeyEntry = "entry";
|
||||
public const String KeyParent = "parent";
|
||||
public const String KeyTemplateUuid = "KeyTemplateUuid";
|
||||
|
||||
public const int ResultOkIconPicker = (int)Result.FirstUser + 1000;
|
||||
|
||||
|
@ -64,11 +71,12 @@ namespace keepass2android
|
|||
act.StartActivityForResult(i, 0);
|
||||
}
|
||||
|
||||
public static void Launch(Activity act, PwGroup pw, AppTask appTask) {
|
||||
public static void Launch(Activity act, PwGroup pw, PwUuid templateUuid, AppTask appTask) {
|
||||
Intent i = new Intent(act, typeof(EntryEditActivity));
|
||||
|
||||
PwGroup parent = pw;
|
||||
i.PutExtra(KeyParent, parent.Uuid.ToHexString());
|
||||
i.PutExtra(KeyTemplateUuid, templateUuid.ToHexString());
|
||||
|
||||
appTask.ToIntent(i);
|
||||
|
||||
|
@ -127,62 +135,39 @@ namespace keepass2android
|
|||
State.ParentGroup = null;
|
||||
if (entryId.Equals(PwUuid.Zero))
|
||||
{
|
||||
//creating new entry
|
||||
String groupId = i.GetStringExtra(KeyParent);
|
||||
State.ParentGroup = db.KpDatabase.RootGroup.FindGroup(new PwUuid(MemUtil.HexStringToByteArray(groupId)), true);
|
||||
|
||||
State.EntryInDatabase = new PwEntry(true, true);
|
||||
State.EntryInDatabase.Strings.Set(PwDefs.UserNameField, new ProtectedString(
|
||||
db.KpDatabase.MemoryProtection.ProtectUserName, db.KpDatabase.DefaultUserName));
|
||||
|
||||
/*KPDesktop
|
||||
* ProtectedString psAutoGen;
|
||||
PwGenerator.Generate(out psAutoGen, Program.Config.PasswordGenerator.AutoGeneratedPasswordsProfile,
|
||||
null, Program.PwGeneratorPool);
|
||||
psAutoGen = psAutoGen.WithProtection(pwDb.MemoryProtection.ProtectPassword);
|
||||
pwe.Strings.Set(PwDefs.PasswordField, psAutoGen);
|
||||
|
||||
int nExpireDays = Program.Config.Defaults.NewEntryExpiresInDays;
|
||||
if(nExpireDays >= 0)
|
||||
{
|
||||
pwe.Expires = true;
|
||||
pwe.ExpiryTime = DateTime.Now.AddDays(nExpireDays);
|
||||
}*/
|
||||
|
||||
if ((State.ParentGroup.IconId != PwIcon.Folder) && (State.ParentGroup.IconId != PwIcon.FolderOpen) &&
|
||||
(State.ParentGroup.IconId != PwIcon.FolderPackage))
|
||||
PwUuid templateId = new PwUuid(MemUtil.HexStringToByteArray(i.GetStringExtra(KeyTemplateUuid)));
|
||||
PwEntry templateEntry = null;
|
||||
if (!PwUuid.Zero.Equals(templateId))
|
||||
{
|
||||
State.EntryInDatabase.IconId = State.ParentGroup.IconId; // Inherit icon from group
|
||||
templateEntry = db.Entries[templateId];
|
||||
}
|
||||
|
||||
if (KpEntryTemplatedEdit.IsTemplate(templateEntry))
|
||||
{
|
||||
CreateNewFromKpEntryTemplate(db, templateEntry);
|
||||
}
|
||||
else if (templateEntry != null)
|
||||
{
|
||||
CreateNewFromStandardTemplate(templateEntry);
|
||||
}
|
||||
else
|
||||
State.EntryInDatabase.IconId = PwIcon.Key;
|
||||
State.EntryInDatabase.CustomIconUuid = State.ParentGroup.CustomIconUuid;
|
||||
|
||||
/*
|
||||
* KPDesktop
|
||||
if(strDefaultSeq.Length == 0)
|
||||
{
|
||||
PwGroup pg = m_pwEntry.ParentGroup;
|
||||
if(pg != null)
|
||||
{
|
||||
strDefaultSeq = pg.GetAutoTypeSequenceInherited();
|
||||
|
||||
if(strDefaultSeq.Length == 0)
|
||||
{
|
||||
if(PwDefs.IsTanEntry(m_pwEntry))
|
||||
strDefaultSeq = PwDefs.DefaultAutoTypeSequenceTan;
|
||||
else
|
||||
strDefaultSeq = PwDefs.DefaultAutoTypeSequence;
|
||||
CreateNewWithoutTemplate(db);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
_appTask.PrepareNewEntry(State.EntryInDatabase);
|
||||
State.IsNew = true;
|
||||
State.EntryModified = true;
|
||||
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
System.Diagnostics.Debug.Assert(entryId != null);
|
||||
Debug.Assert(entryId != null);
|
||||
|
||||
State.EntryInDatabase = db.Entries [entryId];
|
||||
State.IsNew = false;
|
||||
|
@ -191,6 +176,10 @@ namespace keepass2android
|
|||
}
|
||||
|
||||
State.Entry = State.EntryInDatabase.CloneDeep();
|
||||
if (KpEntryTemplatedEdit.IsTemplated(db, State.Entry))
|
||||
State.EditMode = new KpEntryTemplatedEdit(db, State.Entry);
|
||||
else
|
||||
State.EditMode = new DefaultEdit();
|
||||
|
||||
}
|
||||
|
||||
|
@ -200,6 +189,7 @@ namespace keepass2android
|
|||
SetResult(KeePass.ExitRefreshTitle);
|
||||
|
||||
|
||||
|
||||
FillData();
|
||||
View scrollView = FindViewById(Resource.Id.entry_scroll);
|
||||
scrollView.ScrollBarStyle = ScrollbarStyles.InsideInset;
|
||||
|
@ -250,8 +240,8 @@ namespace keepass2android
|
|||
State.ShowPassword = !State.ShowPassword;
|
||||
MakePasswordVisibleOrHidden();
|
||||
};
|
||||
Android.Graphics.PorterDuff.Mode mMode = Android.Graphics.PorterDuff.Mode.SrcAtop;
|
||||
Android.Graphics.Color color = new Android.Graphics.Color (189,189,189);
|
||||
PorterDuff.Mode mMode = PorterDuff.Mode.SrcAtop;
|
||||
Color color = new Color (189,189,189);
|
||||
btnTogglePassword.SetColorFilter (color, mMode);
|
||||
|
||||
|
||||
|
@ -288,6 +278,40 @@ namespace keepass2android
|
|||
|
||||
}
|
||||
|
||||
private void CreateNewFromKpEntryTemplate(Database db, PwEntry templateEntry)
|
||||
{
|
||||
var entry = new PwEntry(true, true);
|
||||
KpEntryTemplatedEdit.InitializeEntry(entry, templateEntry);
|
||||
|
||||
|
||||
State.EntryInDatabase = entry;
|
||||
}
|
||||
|
||||
private void CreateNewFromStandardTemplate(PwEntry templateEntry)
|
||||
{
|
||||
var newEntry = templateEntry.CloneDeep();
|
||||
newEntry.SetUuid(new PwUuid(true), true); // Create new UUID
|
||||
newEntry.CreationTime = newEntry.LastModificationTime = newEntry.LastAccessTime = DateTime.Now;
|
||||
State.EntryInDatabase = newEntry;
|
||||
}
|
||||
|
||||
private void CreateNewWithoutTemplate(Database db)
|
||||
{
|
||||
State.EntryInDatabase = new PwEntry(true, true);
|
||||
State.EntryInDatabase.Strings.Set(PwDefs.UserNameField, new ProtectedString(
|
||||
db.KpDatabase.MemoryProtection.ProtectUserName, db.KpDatabase.DefaultUserName));
|
||||
|
||||
if ((State.ParentGroup.IconId != PwIcon.Folder) && (State.ParentGroup.IconId != PwIcon.FolderOpen) &&
|
||||
(State.ParentGroup.IconId != PwIcon.FolderPackage))
|
||||
{
|
||||
State.EntryInDatabase.IconId = State.ParentGroup.IconId; // Inherit icon from group
|
||||
}
|
||||
else
|
||||
State.EntryInDatabase.IconId = PwIcon.Key;
|
||||
State.EntryInDatabase.CustomIconUuid = State.ParentGroup.CustomIconUuid;
|
||||
|
||||
}
|
||||
|
||||
private void SetAddExtraStringEnabled()
|
||||
{
|
||||
if (!App.Kp2a.GetDb().DatabaseFormat.CanHaveCustomFields)
|
||||
|
@ -785,6 +809,7 @@ namespace keepass2android
|
|||
public override bool OnPrepareOptionsMenu(IMenu menu)
|
||||
{
|
||||
Util.PrepareDonateOptionMenu(menu, this);
|
||||
menu.FindItem(Resource.Id.menu_show_all).SetVisible(_editModeHiddenViews.Any());
|
||||
return base.OnPrepareOptionsMenu(menu);
|
||||
}
|
||||
|
||||
|
@ -806,6 +831,11 @@ namespace keepass2android
|
|||
case Resource.Id.menu_cancel:
|
||||
Finish();
|
||||
return true;
|
||||
case Resource.Id.menu_show_all:
|
||||
item.SetVisible(false);
|
||||
foreach (View v in _editModeHiddenViews)
|
||||
v.Visibility = ViewStates.Visible;
|
||||
return true;
|
||||
case Android.Resource.Id.Home:
|
||||
OnBackPressed();
|
||||
return true;
|
||||
|
@ -849,11 +879,12 @@ namespace keepass2android
|
|||
((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(ees);
|
||||
ees.FindViewById(Resource.Id.edit_extra).Click += (sender, e) => EditAdvancedString(ees.FindViewById(Resource.Id.edit_extra));
|
||||
return ees;
|
||||
}
|
||||
|
||||
private string[] _additionalKeys = null;
|
||||
private List<View> _editModeHiddenViews;
|
||||
|
||||
public string[] AdditionalKeys
|
||||
{
|
||||
|
@ -864,6 +895,7 @@ namespace keepass2android
|
|||
_additionalKeys = App.Kp2a.GetDb().Entries
|
||||
.Select(kvp => kvp.Value)
|
||||
.SelectMany(x => x.Strings.GetKeys().Where(k => !PwDefs.IsStandardField(k)))
|
||||
.Where(k => (k != null) && !k.StartsWith("_etm_") )
|
||||
.Distinct()
|
||||
.ToArray();
|
||||
}
|
||||
|
@ -934,7 +966,9 @@ namespace keepass2android
|
|||
}
|
||||
}
|
||||
|
||||
private void FillData() {
|
||||
private void FillData()
|
||||
{
|
||||
_editModeHiddenViews = new List<View>();
|
||||
ImageButton currIconButton = (ImageButton) FindViewById(Resource.Id.icon_button);
|
||||
App.Kp2a.GetDb().DrawableFactory.AssignDrawableTo(currIconButton, this, App.Kp2a.GetDb().KpDatabase, State.Entry.IconId, State.Entry.CustomIconUuid, false);
|
||||
|
||||
|
@ -950,12 +984,15 @@ namespace keepass2android
|
|||
|
||||
LinearLayout container = (LinearLayout) FindViewById(Resource.Id.advanced_container);
|
||||
|
||||
foreach (var pair in State.Entry.Strings)
|
||||
foreach (var key in State.EditMode.SortExtraFieldKeys(State.Entry.Strings.Select(ps => ps.Key)))
|
||||
{
|
||||
String key = pair.Key;
|
||||
|
||||
if (!PwDefs.IsStandardField(key)) {
|
||||
var ees = CreateExtraStringView(pair);
|
||||
if (!PwDefs.IsStandardField(key))
|
||||
{
|
||||
RelativeLayout ees = CreateExtraStringView(new KeyValuePair<string, ProtectedString>(key, State.Entry.Strings.Get(key)));
|
||||
var isVisible = State.EditMode.IsVisible(key);
|
||||
ees.Visibility = isVisible ? ViewStates.Visible : ViewStates.Gone;
|
||||
if (!isVisible)
|
||||
_editModeHiddenViews.Add(ees);
|
||||
container.AddView(ees);
|
||||
}
|
||||
}
|
||||
|
@ -985,6 +1022,29 @@ namespace keepass2android
|
|||
|
||||
|
||||
UpdateExpires();
|
||||
|
||||
List<KeyValuePair<string, int>> keyLayoutIds = new List<KeyValuePair<string, int>>()
|
||||
{
|
||||
new KeyValuePair<string, int>(PwDefs.TitleField, Resource.Id.title_section),
|
||||
new KeyValuePair<string, int>(PwDefs.UserNameField, Resource.Id.user_section),
|
||||
new KeyValuePair<string, int>(PwDefs.PasswordField, Resource.Id.password_section),
|
||||
new KeyValuePair<string, int>(PwDefs.UrlField, Resource.Id.url_section),
|
||||
new KeyValuePair<string, int>(PwDefs.NotesField, Resource.Id.comments_section),
|
||||
new KeyValuePair<string, int>(KeePass.TagsKey, Resource.Id.tags_section),
|
||||
new KeyValuePair<string, int>(KeePass.OverrideUrlKey, Resource.Id.entry_override_url_container),
|
||||
new KeyValuePair<string, int>(KeePass.ExpDateKey, Resource.Id.expires_section),
|
||||
};
|
||||
foreach (var kvp in keyLayoutIds)
|
||||
{
|
||||
var isVisible = State.EditMode.IsVisible(kvp.Key);
|
||||
var field = FindViewById(kvp.Value);
|
||||
if (!isVisible)
|
||||
_editModeHiddenViews.Add(field);
|
||||
|
||||
field.Visibility = isVisible ? ViewStates.Visible : ViewStates.Gone;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
private String getDateTime(DateTime dt) {
|
||||
return dt.ToString ("g", CultureInfo.CurrentUICulture);
|
||||
|
@ -1052,7 +1112,7 @@ namespace keepass2android
|
|||
|
||||
if (allKeys.Contains(key))
|
||||
{
|
||||
Toast.MakeText(this, GetString(Resource.String.error_string_duplicate_key, new Java.Lang.Object[]{key}), ToastLength.Long).Show();
|
||||
Toast.MakeText(this, GetString(Resource.String.error_string_duplicate_key, new Object[]{key}), ToastLength.Long).Show();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1083,9 +1143,34 @@ namespace keepass2android
|
|||
base.OnPause();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class DefaultEdit : IEditMode
|
||||
{
|
||||
public DefaultEdit()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool IsVisible(string fieldKey)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public IEnumerable<string> SortExtraFieldKeys(IEnumerable<string> keys)
|
||||
{
|
||||
return keys;
|
||||
}
|
||||
|
||||
public bool ShowAddAttachments
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public bool ShowAddExtras
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,16 @@
|
|||
using System.Collections.Generic;
|
||||
using KeePassLib;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
interface IEditMode
|
||||
{
|
||||
bool IsVisible(string fieldKey);
|
||||
|
||||
IEnumerable<string> SortExtraFieldKeys(IEnumerable<string> keys);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Holds the state of the EntrryEditActivity. This is required to be able to keep a partially modified entry in memory
|
||||
/// through the App variable. Serializing this state (especially the Entry/EntryInDatabase) can be a performance problem
|
||||
|
@ -20,6 +29,7 @@ namespace keepass2android
|
|||
|
||||
internal bool EntryModified;
|
||||
|
||||
public IEditMode EditMode { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,9 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
|
@ -26,9 +29,15 @@ using Android.Util;
|
|||
using KeePassLib.Utility;
|
||||
using keepass2android.view;
|
||||
using Android.Content.PM;
|
||||
using Android.Graphics;
|
||||
using Android.Graphics.Drawables;
|
||||
using Android.Preferences;
|
||||
using Android.Runtime;
|
||||
using Android.Support.V4.View;
|
||||
using Android.Support.V7.App;
|
||||
using KeePassLib.Security;
|
||||
using AlertDialog = Android.App.AlertDialog;
|
||||
using Object = Java.Lang.Object;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
|
@ -96,7 +105,77 @@ namespace keepass2android
|
|||
{
|
||||
get { return App.Kp2a.GetDb().CanWrite && ((this.Group.ParentGroup != null) || App.Kp2a.GetDb().DatabaseFormat.CanHaveEntriesInRootGroup); }
|
||||
}
|
||||
|
||||
|
||||
private class TemplateListAdapter : ArrayAdapter<PwEntry>
|
||||
{
|
||||
public TemplateListAdapter(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer)
|
||||
{
|
||||
}
|
||||
|
||||
public TemplateListAdapter(Context context, int textViewResourceId) : base(context, textViewResourceId)
|
||||
{
|
||||
}
|
||||
|
||||
public TemplateListAdapter(Context context, int resource, int textViewResourceId) : base(context, resource, textViewResourceId)
|
||||
{
|
||||
}
|
||||
|
||||
public TemplateListAdapter(Context context, int textViewResourceId, PwEntry[] objects) : base(context, textViewResourceId, objects)
|
||||
{
|
||||
}
|
||||
|
||||
public TemplateListAdapter(Context context, int resource, int textViewResourceId, PwEntry[] objects) : base(context, resource, textViewResourceId, objects)
|
||||
{
|
||||
}
|
||||
|
||||
public TemplateListAdapter(Context context, int textViewResourceId, IList<PwEntry> objects) : base(context, textViewResourceId, objects)
|
||||
{
|
||||
}
|
||||
|
||||
public TemplateListAdapter(Context context, int resource, int textViewResourceId, IList<PwEntry> objects) : base(context, resource, textViewResourceId, objects)
|
||||
{
|
||||
}
|
||||
|
||||
public override View GetView(int position, View convertView, ViewGroup parent)
|
||||
{
|
||||
View v = base.GetView(position, convertView, parent);
|
||||
|
||||
TextView tv = (TextView)v.FindViewById(Android.Resource.Id.Text1);
|
||||
tv.SetPadding(tv.PaddingLeft,0,tv.PaddingRight,0);
|
||||
|
||||
PwEntry templateEntry = this.GetItem(position);
|
||||
|
||||
var bmp =
|
||||
Bitmap.CreateScaledBitmap(
|
||||
Util.DrawableToBitmap(App.Kp2a.GetDb()
|
||||
.DrawableFactory.GetIconDrawable(Context, App.Kp2a.GetDb().KpDatabase, templateEntry.IconId, PwUuid.Zero, false)),
|
||||
(int)Util.convertDpToPixel(80, Context),
|
||||
(int)Util.convertDpToPixel(80, Context),
|
||||
true);
|
||||
|
||||
|
||||
Drawable icon = new BitmapDrawable(bmp);
|
||||
|
||||
if (
|
||||
PreferenceManager.GetDefaultSharedPreferences(Context)
|
||||
.GetString("IconSetKey", Context.PackageName) == Context.PackageName)
|
||||
{
|
||||
Android.Graphics.PorterDuff.Mode mMode = Android.Graphics.PorterDuff.Mode.SrcAtop;
|
||||
Color color = new Color(189, 189, 189);
|
||||
icon.SetColorFilter(color, mMode);
|
||||
}
|
||||
|
||||
//Put the image on the TextView
|
||||
tv.SetCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
|
||||
tv.Text = templateEntry.Strings.ReadSafe(PwDefs.TitleField);
|
||||
tv.SetTextSize(ComplexUnitType.Dip, 20);
|
||||
|
||||
tv.CompoundDrawablePadding = (int)Util.convertDpToPixel(8, Context);
|
||||
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
protected override void OnCreate (Bundle savedInstanceState)
|
||||
{
|
||||
base.OnCreate (savedInstanceState);
|
||||
|
@ -139,7 +218,29 @@ namespace keepass2android
|
|||
if (AddEntryEnabled)
|
||||
{
|
||||
View addEntry = FindViewById (Resource.Id.fabAddNewEntry);
|
||||
addEntry.Click += (sender, e) => { EntryEditActivity.Launch (this, Group, AppTask); };
|
||||
addEntry.Click += (sender, e) =>
|
||||
{
|
||||
PwEntry defaultTemplate = new PwEntry(false, false);
|
||||
defaultTemplate.IconId = PwIcon.Key;
|
||||
defaultTemplate.Strings.Set(PwDefs.TitleField, new ProtectedString(false, GetString(Resource.String.DefaultTemplate)));
|
||||
List<PwEntry> templates = new List<PwEntry>() { defaultTemplate };
|
||||
if (!PwUuid.Zero.Equals(App.Kp2a.GetDb().KpDatabase.EntryTemplatesGroup))
|
||||
{
|
||||
templates.AddRange(App.Kp2a.GetDb().Groups[App.Kp2a.GetDb().KpDatabase.EntryTemplatesGroup].Entries.OrderBy(entr => entr.Strings.ReadSafe(PwDefs.TitleField)));
|
||||
}
|
||||
|
||||
new AlertDialog.Builder(this)
|
||||
.SetAdapter(new TemplateListAdapter(this, Android.Resource.Layout.SelectDialogItem,
|
||||
Android.Resource.Id.Text1, templates), (o, args) =>
|
||||
{
|
||||
|
||||
EntryEditActivity.Launch(this, Group, templates[args.Which].Uuid, AppTask);
|
||||
})
|
||||
.Show();
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -180,32 +180,6 @@ namespace keepass2android
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static Bitmap DrawableToBitmap (Drawable drawable) {
|
||||
Bitmap bitmap = null;
|
||||
|
||||
if (drawable is BitmapDrawable) {
|
||||
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
|
||||
if(bitmapDrawable.Bitmap != null) {
|
||||
return bitmapDrawable.Bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
if(drawable.IntrinsicWidth <= 0 || drawable.IntrinsicHeight <= 0) {
|
||||
bitmap = Bitmap.CreateBitmap(1, 1, Bitmap.Config.Argb8888); // Single color bitmap will be created of 1x1 pixel
|
||||
} else {
|
||||
bitmap = Bitmap.CreateBitmap(drawable.IntrinsicWidth, drawable.IntrinsicHeight, Bitmap.Config.Argb8888);
|
||||
}
|
||||
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
drawable.SetBounds(0, 0, canvas.Width, canvas.Height);
|
||||
drawable.Draw(canvas);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override View GetView(int position, View convertView, ViewGroup parent)
|
||||
{
|
||||
View currView;
|
||||
|
@ -226,7 +200,7 @@ public static Bitmap DrawableToBitmap (Drawable drawable) {
|
|||
tv.Text = "" + position;
|
||||
var drawable = App.Kp2a.GetDb()
|
||||
.DrawableFactory.GetIconDrawable(_act, App.Kp2a.GetDb().KpDatabase, (KeePassLib.PwIcon) position, null, false);
|
||||
drawable = new BitmapDrawable(DrawableToBitmap(drawable));
|
||||
drawable = new BitmapDrawable(Util.DrawableToBitmap(drawable));
|
||||
iv.SetImageDrawable(drawable);
|
||||
//App.Kp2a.GetDb().DrawableFactory.AssignDrawableTo(iv, _act, App.Kp2a.GetDb().KpDatabase, (KeePassLib.PwIcon) position, null, false);
|
||||
|
||||
|
|
|
@ -86,6 +86,11 @@ namespace keepass2android
|
|||
public const Result ExitFileStorageSelectionOk = Result.FirstUser + 8;
|
||||
public const Result ResultOkPasswordGenerator = Result.FirstUser + 9;
|
||||
|
||||
public const string TagsKey = "@tags";
|
||||
public const string OverrideUrlKey = "@override";
|
||||
public const string ExpDateKey = "@exp_date";
|
||||
|
||||
|
||||
AppTask _appTask;
|
||||
private ActivityDesign _design;
|
||||
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using KeePassLib;
|
||||
using KeePassLib.Security;
|
||||
using KeePassLib.Utility;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
class KpEntryTemplatedEdit : IEditMode
|
||||
{
|
||||
internal class KeyOrderComparer : IComparer<string>
|
||||
{
|
||||
private readonly KpEntryTemplatedEdit _kpEntryTemplatedEdit;
|
||||
|
||||
public KeyOrderComparer(KpEntryTemplatedEdit kpEntryTemplatedEdit)
|
||||
{
|
||||
_kpEntryTemplatedEdit = kpEntryTemplatedEdit;
|
||||
}
|
||||
|
||||
public int Compare(string x, string y)
|
||||
{
|
||||
int orderX = _kpEntryTemplatedEdit.GetPosition(x);
|
||||
int orderY = _kpEntryTemplatedEdit.GetPosition(y);
|
||||
if (orderX == orderY)
|
||||
return String.Compare(x, y, StringComparison.CurrentCulture);
|
||||
else
|
||||
return orderX.CompareTo(orderY);
|
||||
}
|
||||
}
|
||||
|
||||
private int GetPosition(string key)
|
||||
{
|
||||
int res;
|
||||
if (!Int32.TryParse(_templateEntry.Strings.ReadSafe("_etm_position_" + key), out res))
|
||||
return Int32.MaxValue;
|
||||
return res;
|
||||
}
|
||||
|
||||
private const string EtmTemplateUuid = "_etm_template_uuid";
|
||||
private const string EtmTitle = "_etm_title_";
|
||||
private readonly Database _db;
|
||||
private readonly PwEntry _entry;
|
||||
private readonly PwEntry _templateEntry;
|
||||
|
||||
public static bool IsTemplated(Database db, PwEntry entry)
|
||||
{
|
||||
if (entry.Strings.Exists(EtmTemplateUuid))
|
||||
{
|
||||
PwUuid templateUuid = new PwUuid(MemUtil.HexStringToByteArray(entry.Strings.ReadSafe(EtmTemplateUuid)));
|
||||
return db.Entries.ContainsKey(templateUuid);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public KpEntryTemplatedEdit(Database db, PwEntry entry)
|
||||
{
|
||||
_db = db;
|
||||
_entry = entry;
|
||||
PwUuid templateUuid = new PwUuid(MemUtil.HexStringToByteArray(entry.Strings.ReadSafe(EtmTemplateUuid)));
|
||||
_templateEntry = db.Entries[templateUuid];
|
||||
}
|
||||
|
||||
public static void InitializeEntry(PwEntry entry, PwEntry templateEntry)
|
||||
{
|
||||
entry.Strings.Set("_etm_template_uuid", new ProtectedString(false, templateEntry.Uuid.ToHexString()));
|
||||
entry.IconId = templateEntry.IconId;
|
||||
|
||||
foreach (string name in templateEntry.Strings.GetKeys())
|
||||
{
|
||||
if (name.StartsWith(EtmTitle))
|
||||
{
|
||||
String fieldName = name.Substring(EtmTitle.Length);
|
||||
|
||||
if (fieldName.StartsWith("@"))
|
||||
{
|
||||
if (fieldName == KeePass.TagsKey) entry.Tags = templateEntry.Tags;
|
||||
if (fieldName == KeePass.OverrideUrlKey) entry.OverrideUrl = templateEntry.OverrideUrl;
|
||||
if (fieldName == KeePass.ExpDateKey)
|
||||
{
|
||||
entry.Expires = templateEntry.Expires;
|
||||
if (entry.Expires)
|
||||
entry.ExpiryTime = templateEntry.ExpiryTime;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
String type = templateEntry.Strings.ReadSafe("_etm_type_" + fieldName);
|
||||
|
||||
if (type == "Divider")
|
||||
continue;
|
||||
|
||||
bool protectedField = type.StartsWith("Protected");
|
||||
entry.Strings.Set(fieldName, new ProtectedString(protectedField, templateEntry.Strings.ReadSafe(fieldName)));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsVisible(string fieldKey)
|
||||
{
|
||||
if (fieldKey == EtmTemplateUuid)
|
||||
return false;
|
||||
if (fieldKey == PwDefs.TitleField)
|
||||
return true;
|
||||
|
||||
if ((fieldKey.StartsWith("@") || (PwDefs.IsStandardField(fieldKey))))
|
||||
{
|
||||
return !String.IsNullOrEmpty(GetFieldValue(fieldKey))
|
||||
|| _templateEntry.Strings.Exists(EtmTitle+fieldKey);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private string GetFieldValue(string fieldKey)
|
||||
{
|
||||
if (fieldKey == KeePass.ExpDateKey)
|
||||
return _entry.Expires ? _entry.ExpiryTime.ToString(CultureInfo.CurrentUICulture) : "";
|
||||
if (fieldKey == KeePass.OverrideUrlKey)
|
||||
return _entry.OverrideUrl;
|
||||
if (fieldKey == KeePass.TagsKey)
|
||||
return StrUtil.TagsToString(_entry.Tags, true);
|
||||
return _entry.Strings.ReadSafe(fieldKey);
|
||||
}
|
||||
|
||||
public IEnumerable<string> SortExtraFieldKeys(IEnumerable<string> keys)
|
||||
{
|
||||
var c = new KeyOrderComparer(this);
|
||||
return keys.OrderBy(s => s, c);
|
||||
}
|
||||
|
||||
public bool ShowAddAttachments
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public bool ShowAddExtras
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public static bool IsTemplate(PwEntry entry)
|
||||
{
|
||||
if (entry == null) return false;
|
||||
return entry.Strings.Exists("_etm_template");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@
|
|||
android:padding="16dp">
|
||||
<!-- Title -->
|
||||
<RelativeLayout
|
||||
android:id="@+id/title_section"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageButton
|
||||
|
@ -35,6 +36,7 @@
|
|||
</RelativeLayout>
|
||||
<!--User-->
|
||||
<LinearLayout
|
||||
android:id="@+id/user_section"
|
||||
style="@style/EntryEditSingleLine_container">
|
||||
<ImageView
|
||||
style="@style/EntryEditSingleLine_ImageView"
|
||||
|
@ -50,7 +52,8 @@
|
|||
</android.support.design.widget.TextInputLayout>
|
||||
</LinearLayout>
|
||||
<!-- password-->
|
||||
<LinearLayout
|
||||
<LinearLayout
|
||||
android:id="@+id/password_section"
|
||||
style="@style/EntryEditSingleLine_container">
|
||||
<ImageView
|
||||
style="@style/EntryEditSingleLine_ImageView"
|
||||
|
@ -111,7 +114,8 @@
|
|||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<!-- URL -->
|
||||
<LinearLayout
|
||||
<LinearLayout
|
||||
android:id="@+id/url_section"
|
||||
style="@style/EntryEditSingleLine_container">
|
||||
<ImageView
|
||||
style="@style/EntryEditSingleLine_ImageView"
|
||||
|
@ -127,7 +131,8 @@
|
|||
</android.support.design.widget.TextInputLayout>
|
||||
</LinearLayout>
|
||||
<!-- Comments -->
|
||||
<LinearLayout
|
||||
<LinearLayout
|
||||
android:id="@+id/comments_section"
|
||||
style="@style/EntryEditSingleLine_container">
|
||||
<ImageView
|
||||
style="@style/EntryEditSingleLine_ImageView"
|
||||
|
@ -141,8 +146,8 @@
|
|||
android:inputType="textMultiLine" />
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/entry_extras_label"
|
||||
<LinearLayout
|
||||
android:id="@+id/entry_extras_container"
|
||||
style="@style/EntryEditSingleLine_container">
|
||||
<ImageView
|
||||
style="@style/EntryEditSingleLine_ImageView"
|
||||
|
@ -197,7 +202,8 @@
|
|||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<!-- Tags -->
|
||||
<LinearLayout
|
||||
<LinearLayout
|
||||
android:id="@+id/tags_section"
|
||||
style="@style/EntryEditSingleLine_container">
|
||||
<ImageView
|
||||
style="@style/EntryEditSingleLine_ImageView"
|
||||
|
@ -230,7 +236,8 @@
|
|||
</android.support.design.widget.TextInputLayout>
|
||||
</LinearLayout>
|
||||
<!--expires-->
|
||||
<LinearLayout
|
||||
<LinearLayout
|
||||
android:id="@+id/expires_section"
|
||||
style="@style/EntryEditSingleLine_container">
|
||||
<ImageView
|
||||
style="@style/EntryEditSingleLine_ImageView"
|
||||
|
|
|
@ -27,4 +27,8 @@
|
|||
android:icon="@drawable/ic_menu_close"
|
||||
app:showAsAction="always"
|
||||
/>
|
||||
<item android:id="@+id/menu_show_all"
|
||||
android:title="@string/menu_show_all"
|
||||
app:showAsAction="never"
|
||||
/>
|
||||
</menu>
|
|
@ -106,7 +106,7 @@
|
|||
<string name="enter_filename">Enter database filename</string>
|
||||
<string name="entry_accessed">Accessed</string>
|
||||
<string name="entry_cancel">Cancel</string>
|
||||
<string name="entry_comment">Comments</string>
|
||||
<string name="entry_comment">Notes</string>
|
||||
<string name="entry_tags">Tags</string>
|
||||
<string name="entry_override_url">Override URL</string>
|
||||
<string name="entry_confpassword">Confirm password</string>
|
||||
|
@ -144,7 +144,7 @@
|
|||
<string name="file_browser">File Browser</string>
|
||||
<string name="generate_password">Generate Password</string>
|
||||
<string name="group">Group</string>
|
||||
<string name="hint_comment">comment</string>
|
||||
<string name="hint_comment">notes</string>
|
||||
<string name="hint_conf_pass">confirm password</string>
|
||||
<string name="hint_generated_password">generated password</string>
|
||||
<string name="hint_group_name">Group name</string>
|
||||
|
@ -194,6 +194,7 @@
|
|||
<string name="menu_search_advanced">Advanced Search</string>
|
||||
<string name="menu_url">Go to URL</string>
|
||||
<string name="menu_change_db">Change database</string>
|
||||
<string name="menu_show_all">Show all fields</string>
|
||||
<string name="minus">Minus</string>
|
||||
<string name="never">Never</string>
|
||||
<string name="yes">Yes</string>
|
||||
|
@ -578,6 +579,8 @@
|
|||
|
||||
<string name="DuplicateTitle">Copy</string>
|
||||
|
||||
<string name="DefaultTemplate">Standard-Eintrag</string>
|
||||
|
||||
|
||||
<string name="ChangeLog_title">Change log</string>
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@ using Android.Views;
|
|||
using Android.Widget;
|
||||
using Android.Content.PM;
|
||||
using Android.Content.Res;
|
||||
using Android.Graphics;
|
||||
using Android.Graphics.Drawables;
|
||||
using Android.Util;
|
||||
using KeePassLib.Serialization;
|
||||
using Uri = Android.Net.Uri;
|
||||
|
@ -38,6 +40,35 @@ namespace keepass2android
|
|||
|
||||
public class Util {
|
||||
|
||||
public static Bitmap DrawableToBitmap(Drawable drawable)
|
||||
{
|
||||
Bitmap bitmap = null;
|
||||
|
||||
if (drawable is BitmapDrawable)
|
||||
{
|
||||
BitmapDrawable bitmapDrawable = (BitmapDrawable)drawable;
|
||||
if (bitmapDrawable.Bitmap != null)
|
||||
{
|
||||
return bitmapDrawable.Bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
if (drawable.IntrinsicWidth <= 0 || drawable.IntrinsicHeight <= 0)
|
||||
{
|
||||
bitmap = Bitmap.CreateBitmap(1, 1, Bitmap.Config.Argb8888); // Single color bitmap will be created of 1x1 pixel
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmap = Bitmap.CreateBitmap(drawable.IntrinsicWidth, drawable.IntrinsicHeight, Bitmap.Config.Argb8888);
|
||||
}
|
||||
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
drawable.SetBounds(0, 0, canvas.Width, canvas.Height);
|
||||
drawable.Draw(canvas);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
public static float convertDpToPixel(float dp, Context context)
|
||||
{
|
||||
Resources resources = context.Resources;
|
||||
|
|
|
@ -149,6 +149,7 @@
|
|||
<Compile Include="icons\DrawableFactory.cs" />
|
||||
<Compile Include="KeeChallenge.cs" />
|
||||
<Compile Include="FixedDrawerLayout.cs" />
|
||||
<Compile Include="KpEntryTemplatedEdit.cs" />
|
||||
<Compile Include="MeasuringRelativeLayout.cs" />
|
||||
<Compile Include="NfcOtpActivity.cs" />
|
||||
<Compile Include="pluginhost\PluginArrayAdapter.cs" />
|
||||
|
|
Loading…
Reference in New Issue