Hide empty field, move code in view, delete EntryActivityV4

This commit is contained in:
J-Jamet
2018-02-18 15:31:56 +01:00
parent c1bf96ac5f
commit d46a6a2ea8
9 changed files with 294 additions and 221 deletions

View File

@@ -105,10 +105,6 @@
android:name="com.keepassdroid.activities.EntryActivity"
android:configChanges="orientation|keyboardHidden"
android:windowSoftInputMode="stateHidden" />
<activity
android:name="com.keepassdroid.activities.EntryActivityV4"
android:configChanges="orientation|keyboardHidden"
android:windowSoftInputMode="stateHidden" />
<activity
android:name="com.keepassdroid.activities.EntryEditActivityV3"
android:configChanges="orientation|keyboardHidden"

View File

@@ -32,6 +32,7 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
@@ -39,7 +40,6 @@ import android.support.v4.app.NotificationCompat;
import android.support.v7.widget.Toolbar;
import android.text.SpannableString;
import android.text.method.LinkMovementMethod;
import android.text.method.PasswordTransformationMethod;
import android.text.util.Linkify;
import android.view.Menu;
import android.view.MenuInflater;
@@ -56,18 +56,22 @@ import com.keepassdroid.database.PwDatabase;
import com.keepassdroid.database.PwEntry;
import com.keepassdroid.database.PwEntryV4;
import com.keepassdroid.database.exception.SamsungClipboardException;
import com.keepassdroid.database.security.ProtectedString;
import com.keepassdroid.intents.Intents;
import com.keepassdroid.settings.PrefsUtil;
import com.keepassdroid.tasks.UIToastTask;
import com.keepassdroid.utils.EmptyUtils;
import com.keepassdroid.utils.MenuUtil;
import com.keepassdroid.utils.SprEngine;
import com.keepassdroid.utils.SprEngineV4;
import com.keepassdroid.utils.Types;
import com.keepassdroid.utils.Util;
import com.keepassdroid.view.EntryContentsView;
import com.kunzisoft.keepass.KeePass;
import com.kunzisoft.keepass.R;
import java.text.DateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
@@ -79,20 +83,10 @@ public class EntryActivity extends LockCloseHideActivity {
public static final int NOTIFY_USERNAME = 1;
public static final int NOTIFY_PASSWORD = 2;
public static void Launch(Activity act, PwEntry pw) {
Intent i;
if ( pw instanceof PwEntryV4 ) {
i = new Intent(act, EntryActivityV4.class);
} else {
i = new Intent(act, EntryActivity.class);
}
i.putExtra(KEY_ENTRY, Types.UUIDtoBytes(pw.getUUID()));
act.startActivityForResult(i, EntryEditActivity.ADD_OR_UPDATE_ENTRY_REQUEST_CODE);
}
private ImageView titleIconView;
private TextView titleView;
private EntryContentsView entryContentsView;
protected PwEntry mEntry;
private Timer mTimer = new Timer();
@@ -100,35 +94,18 @@ public class EntryActivity extends LockCloseHideActivity {
private NotificationManager mNM;
private BroadcastReceiver mIntentReceiver;
protected boolean readOnly = false;
private DateFormat dateFormat;
private DateFormat timeFormat;
protected void setEntryView() {
setContentView(R.layout.entry_view);
}
protected void setupEditButtons() {
View edit = findViewById(R.id.entry_edit);
edit.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
EntryEditActivity.Launch(EntryActivity.this, mEntry);
}
});
if (readOnly) {
edit.setVisibility(View.GONE);
}
}
public static void Launch(Activity act, PwEntry pw) {
Intent intent = new Intent(act, EntryActivity.class);
intent.putExtra(KEY_ENTRY, Types.UUIDtoBytes(pw.getUUID()));
act.startActivityForResult(intent, EntryEditActivity.ADD_OR_UPDATE_ENTRY_REQUEST_CODE);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
mShowPassword = !PrefsUtil.isPasswordMask(this);
super.onCreate(savedInstanceState);
setEntryView();
setContentView(R.layout.entry_view);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
@@ -136,10 +113,6 @@ public class EntryActivity extends LockCloseHideActivity {
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
Context appCtx = getApplicationContext();
dateFormat = android.text.format.DateFormat.getDateFormat(appCtx);
timeFormat = android.text.format.DateFormat.getTimeFormat(appCtx);
Database db = App.getDB();
// Likely the app has been killed exit the activity
@@ -149,11 +122,13 @@ public class EntryActivity extends LockCloseHideActivity {
}
readOnly = db.readOnly;
mShowPassword = !PrefsUtil.isPasswordMask(this);
setResult(KeePass.EXIT_NORMAL);
// Get Entry from UUID
Intent i = getIntent();
UUID uuid = Types.bytestoUUID(i.getByteArrayExtra(KEY_ENTRY));
mEntry = db.pm.entries.get(uuid);
if (mEntry == null) {
Toast.makeText(this, R.string.entry_not_found, Toast.LENGTH_LONG).show();
@@ -166,10 +141,26 @@ public class EntryActivity extends LockCloseHideActivity {
// Update last access time.
mEntry.touch(false, false);
fillData(false);
setupEditButtons();
// Get views
titleIconView = (ImageView) findViewById(R.id.entry_icon);
titleView = (TextView) findViewById(R.id.entry_title);
entryContentsView = (EntryContentsView) findViewById(R.id.entry_contents);
fillData();
// Setup Edit Buttons
View edit = findViewById(R.id.entry_edit);
edit.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
EntryEditActivity.Launch(EntryActivity.this, mEntry);
}
});
if (readOnly) {
edit.setVisibility(View.GONE);
}
// If notifications enabled in settings
if (isClipboardNotificationsEnable(getApplicationContext())) {
@@ -251,48 +242,55 @@ public class EntryActivity extends LockCloseHideActivity {
return notify;
}
private String getDateTime(Date dt) {
return dateFormat.format(dt) + " " + timeFormat.format(dt);
}
protected void fillData(boolean trimList) {
ImageView iv = (ImageView) findViewById(R.id.entry_icon);
private void populateTitle(Drawable drawIcon, String text) {
titleIconView.setImageDrawable(drawIcon);
titleView.setText(text);
}
protected void fillData() {
Database db = App.getDB();
db.drawFactory.assignDrawableTo(iv, getResources(), mEntry.getIcon());
PwDatabase pm = db.pm;
populateText(R.id.entry_title, mEntry.getTitle(true, pm));
populateText(R.id.entry_user_name, mEntry.getUsername(true, pm));
populateText(R.id.entry_url, mEntry.getUrl(true, pm));
populateText(R.id.entry_password, mEntry.getPassword(true, pm));
setPasswordStyle();
populateText(R.id.entry_created, getDateTime(mEntry.getCreationTime()));
populateText(R.id.entry_modified, getDateTime(mEntry.getLastModificationTime()));
populateText(R.id.entry_accessed, getDateTime(mEntry.getLastAccessTime()));
// Assign title
populateTitle(db.drawFactory.getIconDrawable(getResources(), mEntry.getIcon()),
mEntry.getTitle(true, pm));
// Assign basic fields
entryContentsView.assignUserName(mEntry.getUsername(true, pm));
entryContentsView.assignURL(mEntry.getUrl(true, pm));
entryContentsView.assignPassword(mEntry.getPassword(true, pm));
entryContentsView.setHiddenPasswordStyle(!mShowPassword);
entryContentsView.assignComment(mEntry.getNotes(true, pm));
// Assign custom fields
entryContentsView.clearExtraFields();
if (mEntry.getVersion() == 4) {
PwEntryV4 entry = (PwEntryV4) mEntry;
SprEngine spr = SprEngineV4.getInstance(pm);
// Display custom strings
if (entry.strings.size() > 0) {
for (Map.Entry<String, ProtectedString> pair : entry.strings.entrySet()) {
String key = pair.getKey();
if (!PwEntryV4.IsStandardString(key)) {
String text = pair.getValue().toString();
entryContentsView.addExtraField(key, spr.compile(text, entry, pm));
}
}
}
}
// Assign dates
entryContentsView.assignCreationDate(mEntry.getCreationTime());
entryContentsView.assignModificationDate(mEntry.getLastModificationTime());
entryContentsView.assignLastAccessDate(mEntry.getLastAccessTime());
Date expires = mEntry.getExpiryTime();
if ( mEntry.expires() ) {
populateText(R.id.entry_expires, getDateTime(expires));
entryContentsView.assignExpiresDate(expires);
} else {
populateText(R.id.entry_expires, R.string.never);
entryContentsView.assignExpiresDate(getString(R.string.never));
}
populateText(R.id.entry_comment, mEntry.getNotes(true, pm));
}
private void populateText(int viewId, int resId) {
TextView tv = (TextView) findViewById(viewId);
tv.setText(resId);
}
private void populateText(int viewId, String text) {
TextView tv = (TextView) findViewById(viewId);
tv.setText(text);
}
@Override
@@ -300,8 +298,7 @@ public class EntryActivity extends LockCloseHideActivity {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case EntryEditActivity.ADD_OR_UPDATE_ENTRY_REQUEST_CODE:
// TODO CHANGE Fill function to include data
fillData(true);
fillData();
// Transit data in previous Activity
setResult(resultCode, data);
break;
@@ -355,16 +352,6 @@ public class EntryActivity extends LockCloseHideActivity {
return true;
}
private void setPasswordStyle() {
TextView password = (TextView) findViewById(R.id.entry_password);
if ( mShowPassword ) {
password.setTransformationMethod(null);
} else {
password.setTransformationMethod(PasswordTransformationMethod.getInstance());
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
@@ -382,7 +369,7 @@ public class EntryActivity extends LockCloseHideActivity {
item.setIcon(R.drawable.ic_visibility_off_white_24dp);
mShowPassword = true;
}
setPasswordStyle();
entryContentsView.setHiddenPasswordStyle(!mShowPassword);
return true;
case R.id.menu_goto_url:

View File

@@ -1,75 +0,0 @@
/*
* Copyright 2017 Brian Pellin, Jeremy Jamet / Kunzisoft.
*
* This file is part of KeePass DX.
*
* KeePass DX 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.
*
* KeePass DX 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 KeePass DX. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.keepassdroid.activities;
import java.util.Map;
import android.view.View;
import android.view.ViewGroup;
import com.kunzisoft.keepass.R;
import com.keepassdroid.app.App;
import com.keepassdroid.database.PwDatabase;
import com.keepassdroid.database.PwEntryV4;
import com.keepassdroid.database.security.ProtectedString;
import com.keepassdroid.utils.SprEngine;
import com.keepassdroid.utils.SprEngineV4;
import com.keepassdroid.view.EntrySection;
public class EntryActivityV4 extends EntryActivity {
@Override
protected void setEntryView() {
setContentView(R.layout.entry_view);
}
@Override
protected void fillData(boolean trimList) {
super.fillData(trimList);
ViewGroup group = (ViewGroup) findViewById(R.id.extra_strings);
if (trimList) {
group.removeAllViews();
}
PwEntryV4 entry = (PwEntryV4) mEntry;
PwDatabase pm = App.getDB().pm;
SprEngine spr = SprEngineV4.getInstance(pm);
// Display custom strings
if (entry.strings.size() > 0) {
for (Map.Entry<String, ProtectedString> pair : entry.strings.entrySet()) {
String key = pair.getKey();
if (!PwEntryV4.IsStandardString(key)) {
String text = pair.getValue().toString();
View view = new EntrySection(this, null, key, spr.compile(text, entry, pm));
group.addView(view);
}
}
}
}
}

View File

@@ -69,6 +69,11 @@ public abstract class PwEntry extends PwNode implements Cloneable {
return Type.ENTRY;
}
/**
* Get the version of entry, (ie: 4 if kdbx database version is 4)
*/
public abstract int getVersion();
public void assign(PwEntry source) {
icon = source.icon;
}

View File

@@ -191,9 +191,13 @@ public class PwEntryV3 extends PwEntry {
tLastMod = new PwDate(now);
tExpire = new PwDate(NEVER_EXPIRE);
}
}
@Override
public int getVersion() {
return 3;
}
/**
* @return the actual password byte array.
*/

View File

@@ -124,6 +124,11 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger {
}
}
@Override
public int getVersion() {
return 4;
}
@SuppressWarnings("unchecked")
@Override
public PwEntry clone(boolean deepStrings) {

View File

@@ -57,7 +57,7 @@ public class DrawableFactory {
iv.setImageDrawable(draw);
}
private Drawable getIconDrawable(Resources res, PwIcon icon) {
public Drawable getIconDrawable(Resources res, PwIcon icon) {
if (icon instanceof PwIconStandard) {
return getIconDrawable(res, (PwIconStandard) icon);
} else {

View File

@@ -20,29 +20,150 @@
package com.keepassdroid.view;
import android.content.Context;
import android.text.method.PasswordTransformationMethod;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.kunzisoft.keepass.R;
import java.text.DateFormat;
import java.util.Date;
public class EntryContentsView extends LinearLayout {
private View userNameContainerView;
private TextView userNameView;
private View urlContainerView;
private TextView urlView;
private View passwordContainerView;
private TextView passwordView;
private View commentContainerView;
private TextView commentView;
private ViewGroup extrasView;
private DateFormat dateFormat;
private DateFormat timeFormat;
private TextView creationDateView;
private TextView modificationDateView;
private TextView lastAccessDateView;
private TextView expiresDateView;
public EntryContentsView(Context context) {
this(context, null);
}
public EntryContentsView(Context context, AttributeSet attrs) {
super(context, attrs);
dateFormat = android.text.format.DateFormat.getDateFormat(context);
timeFormat = android.text.format.DateFormat.getTimeFormat(context);
inflate(context);
}
private void inflate(Context context) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
assert inflater != null;
inflater.inflate(R.layout.entry_view_contents, this);
userNameContainerView = findViewById(R.id.entry_user_name_container);
userNameView = (TextView) findViewById(R.id.entry_user_name);
urlContainerView = findViewById(R.id.entry_url_container);
urlView = (TextView) findViewById(R.id.entry_url);
passwordContainerView = findViewById(R.id.entry_password_container);
passwordView = (TextView) findViewById(R.id.entry_password);
commentContainerView = findViewById(R.id.entry_comment_container);
commentView = (TextView) findViewById(R.id.entry_comment);
extrasView = (ViewGroup) findViewById(R.id.extra_strings);
creationDateView = (TextView) findViewById(R.id.entry_created);
modificationDateView = (TextView) findViewById(R.id.entry_modified);
lastAccessDateView = (TextView) findViewById(R.id.entry_accessed);
expiresDateView = (TextView) findViewById(R.id.entry_expires);
}
public void assignUserName(String userName) {
if (userName != null && !userName.isEmpty()) {
userNameContainerView.setVisibility(VISIBLE);
userNameView.setText(userName);
}
}
public void assignURL(String url) {
if (url != null && !url.isEmpty()) {
urlContainerView.setVisibility(VISIBLE);
urlView.setText(url);
}
}
public void assignPassword(String password) {
if (password != null && !password.isEmpty()) {
passwordContainerView.setVisibility(VISIBLE);
passwordView.setText(password);
}
}
public void setHiddenPasswordStyle(boolean hiddenStyle) {
if ( !hiddenStyle ) {
passwordView.setTransformationMethod(null);
} else {
passwordView.setTransformationMethod(PasswordTransformationMethod.getInstance());
}
}
public void assignComment(String comment) {
if (comment != null && !comment.isEmpty()) {
commentContainerView.setVisibility(VISIBLE);
commentView.setText(comment);
}
}
public void addExtraField(String title, String value) {
View view = new EntrySection(getContext(), null, title, value);
extrasView.addView(view);
}
public void clearExtraFields() {
extrasView.removeAllViews();
}
private String getDateTime(Date date) {
return dateFormat.format(date) + " " + timeFormat.format(date);
}
public void assignCreationDate(Date date) {
creationDateView.setText(getDateTime(date));
}
public void assignModificationDate(Date date) {
modificationDateView.setText(getDateTime(date));
}
public void assignLastAccessDate(Date date) {
lastAccessDateView.setText(getDateTime(date));
}
public void assignExpiresDate(Date date) {
expiresDateView.setText(getDateTime(date));
}
public void assignExpiresDate(String constString) {
expiresDateView.setText(constString);
}
@Override
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);

View File

@@ -23,56 +23,86 @@
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="vertical">
<!-- Username -->
<android.support.v7.widget.AppCompatTextView android:id="@+id/entry_user_name_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/entry_user_name"
style="@style/KeepassDXStyle.TextAppearance.LabelTextStyle" />
<android.support.v7.widget.AppCompatTextView android:id="@+id/entry_user_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textIsSelectable="true"
style="@style/KeepassDXStyle.TextAppearance.TextEntryItem" />
<LinearLayout
android:id="@+id/entry_user_name_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone">
<android.support.v7.widget.AppCompatTextView android:id="@+id/entry_user_name_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/entry_user_name"
style="@style/KeepassDXStyle.TextAppearance.LabelTextStyle" />
<android.support.v7.widget.AppCompatTextView android:id="@+id/entry_user_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textIsSelectable="true"
style="@style/KeepassDXStyle.TextAppearance.TextEntryItem" />
</LinearLayout>
<!-- URL -->
<android.support.v7.widget.AppCompatTextView android:id="@+id/entry_url_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/entry_url"
style="@style/KeepassDXStyle.TextAppearance.LabelTextStyle" />
<android.support.v7.widget.AppCompatTextView android:id="@+id/entry_url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="all"
android:textIsSelectable="true"
style="@style/KeepassDXStyle.TextAppearance.TextEntryItem" />
<LinearLayout
android:id="@+id/entry_url_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone">
<android.support.v7.widget.AppCompatTextView android:id="@+id/entry_url_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/entry_url"
style="@style/KeepassDXStyle.TextAppearance.LabelTextStyle" />
<android.support.v7.widget.AppCompatTextView android:id="@+id/entry_url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="all"
android:textIsSelectable="true"
style="@style/KeepassDXStyle.TextAppearance.TextEntryItem" />
</LinearLayout>
<!-- Password -->
<android.support.v7.widget.AppCompatTextView android:id="@+id/entry_password_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/entry_password"
style="@style/KeepassDXStyle.TextAppearance.LabelTextStyle" />
<android.support.v7.widget.AppCompatTextView android:id="@+id/entry_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
style="@style/KeepassDXStyle.TextAppearance.TextEntryItem" />
<LinearLayout
android:id="@+id/entry_password_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone">
<android.support.v7.widget.AppCompatTextView android:id="@+id/entry_password_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/entry_password"
style="@style/KeepassDXStyle.TextAppearance.LabelTextStyle" />
<android.support.v7.widget.AppCompatTextView android:id="@+id/entry_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
style="@style/KeepassDXStyle.TextAppearance.TextEntryItem" />
</LinearLayout>
<!-- Comment -->
<android.support.v7.widget.AppCompatTextView android:id="@+id/entry_comment_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/entry_comment"
android:autoLink="all"
style="@style/KeepassDXStyle.TextAppearance.LabelTextStyle" />
<android.support.v7.widget.AppCompatTextView android:id="@+id/entry_comment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textIsSelectable="true"
style="@style/KeepassDXStyle.TextAppearance.TextEntryItem" />
<LinearLayout
android:id="@+id/entry_comment_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone">
<android.support.v7.widget.AppCompatTextView android:id="@+id/entry_comment_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/entry_comment"
android:autoLink="all"
style="@style/KeepassDXStyle.TextAppearance.LabelTextStyle" />
<android.support.v7.widget.AppCompatTextView android:id="@+id/entry_comment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textIsSelectable="true"
style="@style/KeepassDXStyle.TextAppearance.TextEntryItem" />
</LinearLayout>
<!-- Extras -->
<LinearLayout android:id="@+id/extra_strings"
android:layout_width="match_parent"
android:layout_height="wrap_content"