From 8a2bd23c32c556be608fe7f8aa7c6529e22c248a Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Mon, 2 Aug 2021 17:17:00 +0200 Subject: [PATCH 1/2] Fix default list persistence --- .../keepass/view/DateTimeEditFieldView.kt | 18 +++- .../keepass/view/DateTimeFieldView.kt | 18 +++- .../keepass/view/GenericFieldView.kt | 1 + .../keepass/view/TemplateAbstractView.kt | 82 +++++++++++++------ .../keepass/view/TemplateEditView.kt | 15 +--- .../kunzisoft/keepass/view/TemplateView.kt | 14 ---- .../keepass/view/TextEditFieldView.kt | 2 + .../kunzisoft/keepass/view/TextFieldView.kt | 2 + .../keepass/view/TextSelectFieldView.kt | 13 ++- 9 files changed, 106 insertions(+), 59 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/view/DateTimeEditFieldView.kt b/app/src/main/java/com/kunzisoft/keepass/view/DateTimeEditFieldView.kt index 6173baf55..61e1982e0 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/DateTimeEditFieldView.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/DateTimeEditFieldView.kt @@ -41,6 +41,8 @@ class DateTimeEditFieldView @JvmOverloads constructor(context: Context, private var mDateTime: DateInstant = DateInstant.IN_ONE_MONTH_DATE_TIME + private var mDefault: DateInstant = DateInstant.NEVER_EXPIRES + var setOnDateClickListener: ((DateInstant) -> Unit)? = null init { @@ -68,7 +70,7 @@ class DateTimeEditFieldView @JvmOverloads constructor(context: Context, DateInstant.Type.TIME -> DateInstant.IN_ONE_HOUR_TIME } } else { - DateInstant.NEVER_EXPIRES + mDefault } } @@ -105,7 +107,7 @@ class DateTimeEditFieldView @JvmOverloads constructor(context: Context, return if (activation) mDateTime else - DateInstant.NEVER_EXPIRES + mDefault } set(value) { mDateTime = DateInstant(value.date, mDateTime.type) @@ -124,7 +126,17 @@ class DateTimeEditFieldView @JvmOverloads constructor(context: Context, mDateTime = try { DateInstant(value) } catch (e: Exception) { - DateInstant.NEVER_EXPIRES + mDefault + } + } + + override var default: String + get() = mDefault.toString() + set(value) { + mDefault = try { + DateInstant(value) + } catch (e: Exception) { + mDefault } } diff --git a/app/src/main/java/com/kunzisoft/keepass/view/DateTimeFieldView.kt b/app/src/main/java/com/kunzisoft/keepass/view/DateTimeFieldView.kt index 28bf9434f..b3940650e 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/DateTimeFieldView.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/DateTimeFieldView.kt @@ -44,6 +44,8 @@ class DateTimeFieldView @JvmOverloads constructor(context: Context, private var mActivated: Boolean = false private var mDateTime: DateInstant = DateInstant.IN_ONE_MONTH_DATE_TIME + private var mDefault: DateInstant = DateInstant.NEVER_EXPIRES + var setOnDateClickListener: ((DateInstant) -> Unit)? = null init { @@ -112,7 +114,7 @@ class DateTimeFieldView @JvmOverloads constructor(context: Context, DateInstant.Type.TIME -> DateInstant.IN_ONE_HOUR_TIME } } else { - DateInstant.NEVER_EXPIRES + mDefault } } @@ -124,7 +126,7 @@ class DateTimeFieldView @JvmOverloads constructor(context: Context, return if (activation) mDateTime else - DateInstant.NEVER_EXPIRES + mDefault } set(value) { mDateTime = DateInstant(value.date, mDateTime.type) @@ -139,7 +141,17 @@ class DateTimeFieldView @JvmOverloads constructor(context: Context, mDateTime = try { DateInstant(value) } catch (e: Exception) { - DateInstant.NEVER_EXPIRES + mDefault + } + } + + override var default: String + get() = mDefault.toString() + set(value) { + mDefault = try { + DateInstant(value) + } catch (e: Exception) { + mDefault } } diff --git a/app/src/main/java/com/kunzisoft/keepass/view/GenericFieldView.kt b/app/src/main/java/com/kunzisoft/keepass/view/GenericFieldView.kt index 8a44532fd..9165ac492 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/GenericFieldView.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/GenericFieldView.kt @@ -3,5 +3,6 @@ package com.kunzisoft.keepass.view interface GenericFieldView { var label: String var value: String + var default: String var isFieldVisible: Boolean } \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/view/TemplateAbstractView.kt b/app/src/main/java/com/kunzisoft/keepass/view/TemplateAbstractView.kt index 9b4a0cebe..2085617b4 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/TemplateAbstractView.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/TemplateAbstractView.kt @@ -131,7 +131,8 @@ abstract class TemplateAbstractView< templateAttribute, Field( templateAttribute.label, - ProtectedString(templateAttribute.protected, "") + ProtectedString(templateAttribute.protected, + templateAttribute.default) ), fieldTag ) @@ -223,7 +224,14 @@ abstract class TemplateAbstractView< val indexOldItem = indexCustomFieldIdByName(field.name) if (indexOldItem >= 0) mCustomFieldIds.removeAt(indexOldItem) - mCustomFieldIds.add(FieldId(field.name, itemView!!.id, field.protectedValue.isProtected)) + if (itemView?.id != null) { + mCustomFieldIds.add( + FieldId( + itemView.id, + field + ) + ) + } } return itemView } @@ -441,32 +449,49 @@ abstract class TemplateAbstractView< * ------------- */ - protected data class FieldId(var label: String, var viewId: Int, var protected: Boolean) + protected data class FieldId(var viewId: Int, var field: Field) private fun isStandardFieldName(name: String): Boolean { return TemplateField.isStandardFieldName(name) } protected fun customFieldIdByName(name: String): FieldId? { - return mCustomFieldIds.find { it.label.equals(name, true) } + return mCustomFieldIds.find { it.field.name.equals(name, true) } } protected fun indexCustomFieldIdByName(name: String): Int { - return mCustomFieldIds.indexOfFirst { it.label.equals(name, true) } + return mCustomFieldIds.indexOfFirst { it.field.name.equals(name, true) } } private fun retrieveCustomFieldsFromView(templateFieldNotEmpty: Boolean = false) { mEntryInfo?.customFields = mCustomFieldIds.mapNotNull { - getCustomField(it.label, templateFieldNotEmpty) + getCustomField(it.field.name, templateFieldNotEmpty) }.toMutableList() } protected fun getCustomField(fieldName: String): Field { return getCustomField(fieldName, false) - ?: Field(fieldName, ProtectedString(false, "")) + ?: Field(fieldName, ProtectedString(false)) } - protected abstract fun getCustomField(fieldName: String, templateFieldNotEmpty: Boolean): Field? + protected fun getCustomField(fieldName: String, templateFieldNotEmpty: Boolean): Field? { + customFieldIdByName(fieldName)?.let { fieldId -> + val editView: View? = templateContainerView.findViewById(fieldId.viewId) + ?: customFieldsContainerView.findViewById(fieldId.viewId) + if (editView is GenericFieldView) { + // Do not return field with a default value + val defaultViewValue = if (editView.value == editView.default) "" else editView.value + if (!templateFieldNotEmpty + || (editView.tag == FIELD_CUSTOM_TAG && defaultViewValue.isNotEmpty())) { + return Field( + fieldName, + ProtectedString(fieldId.field.protectedValue.isProtected, defaultViewValue) + ) + } + } + } + return null + } /** * Update a custom field or create a new one if doesn't exists, the old value is lost @@ -483,16 +508,19 @@ abstract class TemplateAbstractView< replaceCustomField(customField, customField, focus) } else { val newCustomView = buildViewForCustomField(customField) - customFieldsContainerView.addView(newCustomView) - val fieldId = FieldId(customField.name, - newCustomView!!.id, - customField.protectedValue.isProtected) - val indexOldItem = indexCustomFieldIdByName(fieldId.label) - if (indexOldItem >= 0) - mCustomFieldIds.removeAt(indexOldItem) - mCustomFieldIds.add(indexOldItem, fieldId) - if (focus) - newCustomView.requestFocus() + newCustomView?.let { + customFieldsContainerView.addView(newCustomView) + val fieldId = FieldId( + newCustomView.id, + customField + ) + val indexOldItem = indexCustomFieldIdByName(fieldId.field.name) + if (indexOldItem >= 0) + mCustomFieldIds.removeAt(indexOldItem) + mCustomFieldIds.add(indexOldItem, fieldId) + if (focus) + newCustomView.requestFocus() + } true } } else { @@ -526,12 +554,18 @@ abstract class TemplateAbstractView< mCustomFieldIds.removeAt(oldPosition) val newCustomView = buildViewForCustomField(newCustomFieldWithValue) - parentGroup.addView(newCustomView, indexInParent) - mCustomFieldIds.add(oldPosition, FieldId(newCustomFieldWithValue.name, - newCustomView!!.id, - newCustomFieldWithValue.protectedValue.isProtected)) - if (focus) - newCustomView.requestFocus() + newCustomView?.let { + parentGroup.addView(newCustomView, indexInParent) + mCustomFieldIds.add( + oldPosition, + FieldId( + newCustomView.id, + newCustomFieldWithValue + ) + ) + if (focus) + newCustomView.requestFocus() + } return true } } diff --git a/app/src/main/java/com/kunzisoft/keepass/view/TemplateEditView.kt b/app/src/main/java/com/kunzisoft/keepass/view/TemplateEditView.kt index 3fd59509b..7ee42f8b9 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/TemplateEditView.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/TemplateEditView.kt @@ -78,6 +78,7 @@ class TemplateEditView @JvmOverloads constructor(context: Context, return context?.let { TextSelectFieldView(it).apply { setItems(templateAttribute.options.getListItems()) + default = field.protectedValue.stringValue setActionClick(templateAttribute, field, this) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_NO @@ -205,20 +206,6 @@ class TemplateEditView @JvmOverloads constructor(context: Context, }?.otpModel } - override fun getCustomField(fieldName: String, templateFieldNotEmpty: Boolean): Field? { - customFieldIdByName(fieldName)?.let { fieldId -> - val editView: View? = templateContainerView.findViewById(fieldId.viewId) - ?: customFieldsContainerView.findViewById(fieldId.viewId) - if (editView is GenericFieldView) { - if (!templateFieldNotEmpty || - (editView.tag == FIELD_CUSTOM_TAG - && editView.value.isNotEmpty())) - return Field(fieldName, ProtectedString(fieldId.protected, editView.value)) - } - } - return null - } - override fun onRestoreEntryInstanceState(state: SavedState) { mTempDateTimeViewId = state.tempDateTimeViewId } diff --git a/app/src/main/java/com/kunzisoft/keepass/view/TemplateView.kt b/app/src/main/java/com/kunzisoft/keepass/view/TemplateView.kt index e20417272..0ed140f7c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/TemplateView.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/TemplateView.kt @@ -133,20 +133,6 @@ class TemplateView @JvmOverloads constructor(context: Context, return emptyCustomFields } - override fun getCustomField(fieldName: String, templateFieldNotEmpty: Boolean): Field? { - customFieldIdByName(fieldName)?.let { fieldId -> - val editView: View? = templateContainerView.findViewById(fieldId.viewId) - ?: customFieldsContainerView.findViewById(fieldId.viewId) - if (editView is GenericFieldView) { - if (!templateFieldNotEmpty || - (editView.tag == FIELD_CUSTOM_TAG - && editView.value.isNotEmpty())) - return Field(fieldName, ProtectedString(fieldId.protected, editView.value)) - } - } - return null - } - /* * OTP Runnable */ diff --git a/app/src/main/java/com/kunzisoft/keepass/view/TextEditFieldView.kt b/app/src/main/java/com/kunzisoft/keepass/view/TextEditFieldView.kt index 3073ddaec..1cdd141d1 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/TextEditFieldView.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/TextEditFieldView.kt @@ -122,6 +122,8 @@ class TextEditFieldView @JvmOverloads constructor(context: Context, valueView.setText(value) } + override var default: String = "" + fun setMaxChars(numberChars: Int) { when { numberChars <= 0 -> { diff --git a/app/src/main/java/com/kunzisoft/keepass/view/TextFieldView.kt b/app/src/main/java/com/kunzisoft/keepass/view/TextFieldView.kt index 61160e8b8..fd4b4117c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/TextFieldView.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/TextFieldView.kt @@ -88,6 +88,8 @@ class TextFieldView @JvmOverloads constructor(context: Context, changeProtectedValueParameters() } + override var default: String = "" + fun setMaxChars(numberChars: Int) { when { numberChars <= 0 -> { diff --git a/app/src/main/java/com/kunzisoft/keepass/view/TextSelectFieldView.kt b/app/src/main/java/com/kunzisoft/keepass/view/TextSelectFieldView.kt index da29237d7..af8f2f059 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/TextSelectFieldView.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/TextSelectFieldView.kt @@ -26,6 +26,7 @@ class TextSelectFieldView @JvmOverloads constructor(context: Context, private var valueViewId = ViewCompat.generateViewId() private var valueSpinnerAdapter = ValueSpinnerAdapter(context) private var actionImageButtonId = ViewCompat.generateViewId() + private var mDefaultPosition = 0 private val labelView = AppCompatTextView(context).apply { setTextAppearance(context, R.style.KeepassDXStyle_TextAppearance_LabelTextStyle) @@ -142,12 +143,22 @@ class TextSelectFieldView @JvmOverloads constructor(context: Context, // To define default value and retrieve selected one override var value: String get() { - return valueSpinnerView.selectedItem?.toString() ?: valueSpinnerAdapter.getItem(0) + var selectedItemString = valueSpinnerView.selectedItem?.toString() + if (selectedItemString.isNullOrEmpty()) { + selectedItemString = valueSpinnerAdapter.getItem(0) + } + return selectedItemString } set(value) { valueSpinnerView.setSelection(valueSpinnerAdapter.getPosition(value)) } + override var default: String + get() = valueSpinnerAdapter.getItem(mDefaultPosition) + set(value) { + mDefaultPosition = valueSpinnerAdapter.getPosition(value) + } + override fun setOnActionClickListener(onActionClickListener: OnClickListener?, @DrawableRes actionImageId: Int?) { actionImageId?.let { From 96d2edb6417cf7d8e126413344bd7f7c7b667266 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Mon, 2 Aug 2021 18:36:42 +0200 Subject: [PATCH 2/2] Fix template after autofill search save --- .../keepass/activities/GroupActivity.kt | 5 +++- .../keepass/database/element/Entry.kt | 10 +++++-- .../com/kunzisoft/keepass/model/EntryInfo.kt | 30 ++++++++----------- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt index c12b42ef0..16b3781d4 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt @@ -695,7 +695,10 @@ class GroupActivity : LockingActivity(), private fun updateEntryWithSearchInfo(entry: Entry, searchInfo: SearchInfo) { val newEntry = Entry(entry) - newEntry.setEntryInfo(mDatabase, newEntry.getEntryInfo(mDatabase, true).apply { + newEntry.setEntryInfo(mDatabase, newEntry.getEntryInfo(mDatabase, + raw = true, + removeTemplateConfiguration = false + ).apply { saveSearchInfo(mDatabase, searchInfo) }) // In selection mode, it's forced read-only, so update not allowed diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/Entry.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/Entry.kt index 45653d35d..445aabac1 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/Entry.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/Entry.kt @@ -397,10 +397,16 @@ class Entry : Node, EntryVersionedInterface { * Retrieve generated entry info. * If are not [raw] data, remove parameter fields and add auto generated elements in auto custom fields */ - fun getEntryInfo(database: Database?, raw: Boolean = false): EntryInfo { + fun getEntryInfo(database: Database?, + raw: Boolean = false, + removeTemplateConfiguration: Boolean = true): EntryInfo { val entryInfo = EntryInfo() // Remove unwanted template fields - (database?.removeTemplateConfiguration(this) ?: this).apply { + val baseInfo = if (removeTemplateConfiguration) + database?.removeTemplateConfiguration(this) ?: this + else + this + baseInfo.apply { if (raw) database?.stopManageEntry(this) else diff --git a/app/src/main/java/com/kunzisoft/keepass/model/EntryInfo.kt b/app/src/main/java/com/kunzisoft/keepass/model/EntryInfo.kt index d920b0991..1d7aa4da6 100644 --- a/app/src/main/java/com/kunzisoft/keepass/model/EntryInfo.kt +++ b/app/src/main/java/com/kunzisoft/keepass/model/EntryInfo.kt @@ -170,24 +170,18 @@ class EntryInfo : NodeInfo { if (database?.allowEntryCustomFields() == true) { val creditCard: CreditCard? = registerInfo.creditCard - - creditCard?.let { cc -> - cc.cardholder?.let { - val v = ProtectedString(false, it) - addUniqueField(Field(TemplateField.LABEL_HOLDER, v)) - } - cc.expiration?.let { - expires = true - expiryTime = DateInstant(cc.expiration.millis) - } - cc.number?.let { - val v = ProtectedString(false, it) - addUniqueField(Field(TemplateField.LABEL_NUMBER, v)) - } - cc.cvv?.let { - val v = ProtectedString(true, it) - addUniqueField(Field(TemplateField.LABEL_CVV, v)) - } + creditCard?.cardholder?.let { + addUniqueField(Field(TemplateField.LABEL_HOLDER, ProtectedString(false, it))) + } + creditCard?.expiration?.let { + expires = true + expiryTime = DateInstant(creditCard.expiration.millis) + } + creditCard?.number?.let { + addUniqueField(Field(TemplateField.LABEL_NUMBER, ProtectedString(false, it))) + } + creditCard?.cvv?.let { + addUniqueField(Field(TemplateField.LABEL_CVV, ProtectedString(true, it))) } } }