Add not referenced fields section and encapsulate code

This commit is contained in:
J-Jamet
2021-06-24 14:18:55 +02:00
parent f13c8d7884
commit 7d679aac0b
10 changed files with 262 additions and 271 deletions

View File

@@ -25,6 +25,7 @@ import android.view.LayoutInflater
import android.widget.CompoundButton
import android.widget.FrameLayout
import android.widget.TextView
import androidx.core.view.isVisible
import com.google.android.material.textfield.TextInputLayout
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.element.DateInstant
@@ -32,7 +33,7 @@ import com.kunzisoft.keepass.database.element.DateInstant
class DateTimeEditView @JvmOverloads constructor(context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0)
: FrameLayout(context, attrs, defStyle) {
: FrameLayout(context, attrs, defStyle), GenericDateTimeView {
private var entryExpiresLabelView: TextInputLayout
private var entryExpiresTextView: TextView
@@ -80,7 +81,7 @@ class DateTimeEditView @JvmOverloads constructor(context: Context,
entryExpiresLabelView.hint = value
}
var activation: Boolean
override var activation: Boolean
get() {
return entryExpiresCheckBox.isChecked
}
@@ -96,7 +97,7 @@ class DateTimeEditView @JvmOverloads constructor(context: Context,
assignExpiresDateText()
}
var dateTime: DateInstant
override var dateTime: DateInstant
get() {
return if (activation)
mDateTime
@@ -107,4 +108,12 @@ class DateTimeEditView @JvmOverloads constructor(context: Context,
mDateTime = value
assignExpiresDateText()
}
override var isFieldVisible: Boolean
get() {
return isVisible
}
set(value) {
isVisible = value
}
}

View File

@@ -33,7 +33,7 @@ import java.util.*
class DateTimeView @JvmOverloads constructor(context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0)
: FrameLayout(context, attrs, defStyle) {
: FrameLayout(context, attrs, defStyle), GenericDateTimeView {
private var dateTimeLabelView: TextView
private var dateTimeValueView: TextView
@@ -71,7 +71,7 @@ class DateTimeView @JvmOverloads constructor(context: Context,
dateTimeLabelView.text = value
}
var activation: Boolean
override var activation: Boolean
get() {
return mActivated
}
@@ -87,7 +87,7 @@ class DateTimeView @JvmOverloads constructor(context: Context,
assignExpiresDateText()
}
var dateTime: DateInstant
override var dateTime: DateInstant
get() {
return if (activation)
mDateTime
@@ -98,4 +98,12 @@ class DateTimeView @JvmOverloads constructor(context: Context,
mDateTime = value
assignExpiresDateText()
}
override var isFieldVisible: Boolean
get() {
return isVisible
}
set(value) {
isVisible = value
}
}

View File

@@ -13,6 +13,7 @@ import androidx.annotation.DrawableRes
import androidx.appcompat.widget.AppCompatImageButton
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.core.view.isVisible
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
import com.kunzisoft.keepass.R
@@ -20,7 +21,7 @@ import com.kunzisoft.keepass.R
class EntryEditFieldView @JvmOverloads constructor(context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0)
: RelativeLayout(context, attrs, defStyle) {
: RelativeLayout(context, attrs, defStyle), GenericEntryFieldView {
private var labelViewId = ViewCompat.generateViewId()
private var valueViewId = ViewCompat.generateViewId()
@@ -90,7 +91,7 @@ class EntryEditFieldView @JvmOverloads constructor(context: Context,
}
}
fun applyFontVisibility(fontInVisibility: Boolean) {
override fun applyFontVisibility(fontInVisibility: Boolean) {
if (fontInVisibility)
valueView.applyFontVisibility()
}
@@ -112,7 +113,7 @@ class EntryEditFieldView @JvmOverloads constructor(context: Context,
buildViews()
}
var value: String
override var value: String
get() {
return valueView.text?.toString() ?: ""
}
@@ -159,4 +160,11 @@ class EntryEditFieldView @JvmOverloads constructor(context: Context,
actionImageButton.visibility = if (onActionClickListener == null) View.GONE else View.VISIBLE
}
override var isFieldVisible: Boolean
get() {
return isVisible
}
set(value) {
isVisible = value
}
}

View File

@@ -39,7 +39,7 @@ import com.kunzisoft.keepass.utils.UriUtil
class EntryFieldView @JvmOverloads constructor(context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0)
: LinearLayout(context, attrs, defStyle) {
: LinearLayout(context, attrs, defStyle), GenericEntryFieldView {
private val labelView: TextView
private val valueView: TextView
@@ -57,7 +57,7 @@ class EntryFieldView @JvmOverloads constructor(context: Context,
copyButtonView.visibility = View.GONE
}
fun applyFontVisibility(fontInVisibility: Boolean) {
override fun applyFontVisibility(fontInVisibility: Boolean) {
if (fontInVisibility)
valueView.applyFontVisibility()
}
@@ -74,7 +74,7 @@ class EntryFieldView @JvmOverloads constructor(context: Context,
labelView.setText(labelId)
}
var value: String
override var value: String
get() {
return valueView.text.toString()
}
@@ -181,6 +181,14 @@ class EntryFieldView @JvmOverloads constructor(context: Context,
copyButtonView.isVisible = onClickActionListener != null
}
override var isFieldVisible: Boolean
get() {
return isVisible
}
set(value) {
isVisible = value
}
enum class ButtonState {
ACTIVATE, DEACTIVATE, GONE
}

View File

@@ -0,0 +1,10 @@
package com.kunzisoft.keepass.view
import com.kunzisoft.keepass.database.element.DateInstant
interface GenericDateTimeView {
var activation: Boolean
var dateTime: DateInstant
var isFieldVisible: Boolean
}

View File

@@ -0,0 +1,8 @@
package com.kunzisoft.keepass.view
interface GenericEntryFieldView {
var value: String
fun applyFontVisibility(fontInVisibility: Boolean)
var isFieldVisible: Boolean
}

View File

@@ -7,6 +7,7 @@ import android.os.Parcel
import android.os.Parcelable
import android.os.Parcelable.Creator
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -15,6 +16,7 @@ import android.widget.FrameLayout
import android.widget.ImageView
import androidx.annotation.IdRes
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.element.DateInstant
import com.kunzisoft.keepass.database.element.Field
import com.kunzisoft.keepass.database.element.icon.IconImage
import com.kunzisoft.keepass.database.element.security.ProtectedString
@@ -42,6 +44,7 @@ abstract class TemplateAbstractView @JvmOverloads constructor(context: Context,
protected var entryIconView: ImageView
protected var templateContainerView: ViewGroup
protected var customFieldsContainerView: SectionView
protected var notReferencedFieldsContainerView: SectionView
init {
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater?
@@ -57,6 +60,7 @@ abstract class TemplateAbstractView @JvmOverloads constructor(context: Context,
templateContainerView.setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical)
}
customFieldsContainerView = findViewById(R.id.custom_fields_container)
notReferencedFieldsContainerView = findViewById(R.id.not_referenced_fields_container)
}
// To show icon image
@@ -82,6 +86,7 @@ abstract class TemplateAbstractView @JvmOverloads constructor(context: Context,
// Build each template section
templateContainerView.removeAllViews()
customFieldsContainerView.removeAllViews()
notReferencedFieldsContainerView.removeAllViews()
mCustomFieldIds.clear()
mTemplate?.let { template ->
@@ -94,33 +99,7 @@ abstract class TemplateAbstractView @JvmOverloads constructor(context: Context,
// Build each attribute
templateSection.attributes.forEach { templateAttribute ->
val fieldTag: String
when {
templateAttribute.label.equals(TemplateField.LABEL_TITLE, true) -> {
throw Exception("title cannot be in template attribute")
}
templateAttribute.label.equals(TemplateField.LABEL_USERNAME, true) -> {
fieldTag = FIELD_USERNAME_TAG
}
templateAttribute.label.equals(TemplateField.LABEL_PASSWORD, true) -> {
fieldTag = FIELD_PASSWORD_TAG
}
templateAttribute.label.equals(TemplateField.LABEL_URL, true) -> {
fieldTag = FIELD_URL_TAG
}
templateAttribute.label.equals(
TemplateField.LABEL_EXPIRATION,
true
) -> {
fieldTag = FIELD_EXPIRES_TAG
}
templateAttribute.label.equals(TemplateField.LABEL_NOTES, true) -> {
fieldTag = FIELD_NOTES_TAG
}
else -> {
fieldTag = FIELD_CUSTOM_TAG
}
}
val fieldTag: String = getTagFromStandardTemplateAttribute(templateAttribute)
val attributeView = buildViewForTemplateField(
templateAttribute,
@@ -139,8 +118,46 @@ abstract class TemplateAbstractView @JvmOverloads constructor(context: Context,
}
}
private fun getTagFromStandardTemplateAttribute(templateAttribute: TemplateAttribute): String {
val fieldTag: String
when {
templateAttribute.label.equals(TemplateField.LABEL_TITLE, true) -> {
throw Exception("title cannot be in template attribute")
}
templateAttribute.label.equals(TemplateField.LABEL_USERNAME, true) -> {
fieldTag = FIELD_USERNAME_TAG
}
templateAttribute.label.equals(TemplateField.LABEL_PASSWORD, true) -> {
fieldTag = FIELD_PASSWORD_TAG
}
templateAttribute.label.equals(TemplateField.LABEL_URL, true) -> {
fieldTag = FIELD_URL_TAG
}
templateAttribute.label.equals(TemplateField.LABEL_EXPIRATION,true) -> {
fieldTag = FIELD_EXPIRES_TAG
}
templateAttribute.label.equals(TemplateField.LABEL_NOTES, true) -> {
fieldTag = FIELD_NOTES_TAG
}
else -> {
fieldTag = FIELD_CUSTOM_TAG
}
}
return fieldTag
}
abstract fun buildHeader()
private fun buildViewForNotReferencedField(field: Field): View? {
val standardFieldTemplateAttribute = TemplateAttribute(
field.name,
TemplateAttributeType.MULTILINE,
field.protectedValue.isProtected,
field.protectedValue.stringValue)
val fieldTag: String = getTagFromStandardTemplateAttribute(standardFieldTemplateAttribute)
return buildViewForTemplateField(standardFieldTemplateAttribute, field, fieldTag)
}
private fun buildViewForCustomField(field: Field): View? {
val customFieldTemplateAttribute = TemplateAttribute(
field.name,
@@ -204,13 +221,142 @@ abstract class TemplateAbstractView @JvmOverloads constructor(context: Context,
protected abstract fun populateViewsWithEntryInfo()
protected fun <T: GenericEntryFieldView, U: GenericDateTimeView>
populateSpecificViewsWithEntryInfo(showEmptyFields: Boolean = true,
actionWithEmptyCustomFields: ((List<FieldId>) -> Unit)? = null) {
mEntryInfo?.let { entryInfo ->
val titleView: T? = findViewWithTag(FIELD_TITLE_TAG)
titleView?.value = entryInfo.title
titleView?.applyFontVisibility(mFontInVisibility)
if (!showEmptyFields && entryInfo.title.isEmpty()) {
titleView?.isFieldVisible = false
}
val userNameView: T? = findViewWithTag(FIELD_USERNAME_TAG)
userNameView?.value = entryInfo.username
userNameView?.applyFontVisibility(mFontInVisibility)
if (!showEmptyFields && entryInfo.username.isEmpty()) {
userNameView?.isFieldVisible = false
}
val passwordView: T? = findViewWithTag(FIELD_PASSWORD_TAG)
passwordView?.value = entryInfo.password
passwordView?.applyFontVisibility(mFontInVisibility)
if (!showEmptyFields && entryInfo.password.isEmpty()) {
passwordView?.isFieldVisible = false
}
var urlView: T? = findViewWithTag(FIELD_URL_TAG)
if (!showEmptyFields && entryInfo.url.isEmpty()) {
urlView?.isFieldVisible = false
} else if (urlView == null && entryInfo.url.isNotEmpty()) {
urlView = buildViewForNotReferencedField(
Field(TemplateField.LABEL_URL,
ProtectedString(false, entryInfo.url))
) as? T?
urlView?.let {
addNotReferencedView(it as View)
}
}
urlView?.value = entryInfo.url
urlView?.applyFontVisibility(mFontInVisibility)
val expirationView: U? = findViewWithTag(FIELD_EXPIRES_TAG)
expirationView?.activation = entryInfo.expires
expirationView?.dateTime = entryInfo.expiryTime
if (!showEmptyFields && !entryInfo.expires) {
expirationView?.isFieldVisible = false
}
val notesView: T? = findViewWithTag(FIELD_NOTES_TAG)
notesView?.value = entryInfo.notes
notesView?.applyFontVisibility(mFontInVisibility)
if (!showEmptyFields && entryInfo.notes.isEmpty()) {
notesView?.isFieldVisible = false
}
customFieldsContainerView.removeAllViews()
val emptyCustomFields = mutableListOf<FieldId>().also { it.addAll(mCustomFieldIds) }
entryInfo.customFields.forEach { customField ->
val indexFieldViewId = indexCustomFieldIdByName(customField.name)
if (indexFieldViewId >= 0) {
// Template contains the custom view
val customFieldId = mCustomFieldIds[indexFieldViewId]
emptyCustomFields.remove(customFieldId)
templateContainerView.findViewById<View>(customFieldId.viewId)
?.let { customView ->
if (customView is GenericEntryFieldView) {
customView.value = customField.protectedValue.stringValue
customView.applyFontVisibility(mFontInVisibility)
} else if (customView is GenericDateTimeView) {
try {
customView.dateTime =
DateInstant(customField.protectedValue.stringValue)
} catch (e: Exception) {
Log.e(TAG, "unable to populate date time view", e)
}
}
}
} else {
// If template view not found, create a new custom view
putCustomField(customField, false)
}
}
actionWithEmptyCustomFields?.invoke(emptyCustomFields)
}
}
protected abstract fun populateEntryInfoWithViews(templateFieldNotEmpty: Boolean)
protected fun <T: GenericEntryFieldView, U: GenericDateTimeView>
populateSpecificEntryInfoWithViews(templateFieldNotEmpty: Boolean) {
if (mEntryInfo == null)
mEntryInfo = EntryInfo()
// Icon already populate
val titleView: T? = findViewWithTag(FIELD_TITLE_TAG)
titleView?.value?.let {
mEntryInfo?.title = it
}
val userNameView: T? = findViewWithTag(FIELD_USERNAME_TAG)
userNameView?.value?.let {
mEntryInfo?.username = it
}
val passwordView: T? = findViewWithTag(FIELD_PASSWORD_TAG)
passwordView?.value?.let {
mEntryInfo?.password = it
}
val urlView: T? = findViewWithTag(FIELD_URL_TAG)
urlView?.value?.let {
mEntryInfo?.url = it
}
val expirationView: U? = findViewWithTag(FIELD_EXPIRES_TAG)
expirationView?.activation?.let {
mEntryInfo?.expires = it
}
expirationView?.dateTime?.let {
mEntryInfo?.expiryTime = it
}
val notesView: T? = findViewWithTag(FIELD_NOTES_TAG)
notesView?.value?.let {
mEntryInfo?.notes = it
}
retrieveCustomFieldsFromView(templateFieldNotEmpty)
}
fun getEntryInfo(): EntryInfo {
populateEntryInfoWithViews(true)
return mEntryInfo ?: EntryInfo()
}
abstract fun populateEntryInfoWithViews(templateFieldNotEmpty: Boolean)
fun reload() {
buildTemplateAndPopulateInfo()
}
@@ -230,6 +376,7 @@ abstract class TemplateAbstractView @JvmOverloads constructor(context: Context,
protected fun getFieldViewById(@IdRes viewId: Int): View? {
return templateContainerView.findViewById(viewId)
?: customFieldsContainerView.findViewById(viewId)
?: notReferencedFieldsContainerView.findViewById(viewId)
}
/* -------------
@@ -347,6 +494,10 @@ abstract class TemplateAbstractView @JvmOverloads constructor(context: Context,
retrieveCustomFieldsFromView()
}
fun addNotReferencedView(view: View) {
notReferencedFieldsContainerView.addView(view)
}
fun putOtpElement(otpElement: OtpElement) {
val otpField = OtpEntryFields.buildOtpField(otpElement,
mEntryInfo?.title, mEntryInfo?.username)
@@ -428,5 +579,7 @@ abstract class TemplateAbstractView @JvmOverloads constructor(context: Context,
const val FIELD_EXPIRES_TAG = "FIELD_EXPIRES_TAG"
const val FIELD_NOTES_TAG = "FIELD_NOTES_TAG"
const val FIELD_CUSTOM_TAG = "FIELD_CUSTOM_TAG"
private val TAG = TemplateAbstractView::class.java.name
}
}

View File

@@ -2,7 +2,6 @@ package com.kunzisoft.keepass.view
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.View
import androidx.annotation.IdRes
import androidx.core.view.isVisible
@@ -16,7 +15,6 @@ import com.kunzisoft.keepass.database.element.template.TemplateAttributeAction
import com.kunzisoft.keepass.database.element.template.TemplateAttributeType
import com.kunzisoft.keepass.database.element.template.TemplateField
import com.kunzisoft.keepass.database.element.template.TemplateField.LABEL_TITLE
import com.kunzisoft.keepass.model.EntryInfo
import com.kunzisoft.keepass.otp.OtpEntryFields
import org.joda.time.DateTime
@@ -191,107 +189,12 @@ class TemplateEditView @JvmOverloads constructor(context: Context,
override fun populateViewsWithEntryInfo() {
mEntryInfo?.let { entryInfo ->
setIcon(entryInfo.icon)
val titleView: EntryEditFieldView? =
findViewWithTag(FIELD_TITLE_TAG)
titleView?.value = entryInfo.title
titleView?.applyFontVisibility(mFontInVisibility)
val userNameView: EntryEditFieldView? =
templateContainerView.findViewWithTag(FIELD_USERNAME_TAG)
userNameView?.value = entryInfo.username
userNameView?.applyFontVisibility(mFontInVisibility)
val passwordView: EntryEditFieldView? =
templateContainerView.findViewWithTag(FIELD_PASSWORD_TAG)
passwordView?.value = entryInfo.password
passwordView?.applyFontVisibility(mFontInVisibility)
val urlView: EntryEditFieldView? = templateContainerView.findViewWithTag(
FIELD_URL_TAG
)
urlView?.value = entryInfo.url
urlView?.applyFontVisibility(mFontInVisibility)
val expirationView: DateTimeEditView? =
templateContainerView.findViewWithTag(FIELD_EXPIRES_TAG)
expirationView?.activation = entryInfo.expires
expirationView?.dateTime = entryInfo.expiryTime
val notesView: EntryEditFieldView? =
templateContainerView.findViewWithTag(FIELD_NOTES_TAG)
notesView?.value = entryInfo.notes
notesView?.applyFontVisibility(mFontInVisibility)
customFieldsContainerView.removeAllViews()
entryInfo.customFields.forEach { customField ->
val indexFieldViewId = indexCustomFieldIdByName(customField.name)
if (indexFieldViewId >= 0) {
// Template contains the custom view
val customFieldId = mCustomFieldIds[indexFieldViewId]
templateContainerView.findViewById<View>(customFieldId.viewId)
?.let { customView ->
if (customView is EntryEditFieldView) {
customView.value = customField.protectedValue.stringValue
customView.applyFontVisibility(mFontInVisibility)
} else if (customView is DateTimeEditView) {
try {
customView.dateTime =
DateInstant(customField.protectedValue.stringValue)
} catch (e: Exception) {
Log.e(TAG, "unable to populate date time view", e)
}
}
}
} else {
// If template view not found, create a new custom view
putCustomField(customField, false)
}
}
}
populateSpecificViewsWithEntryInfo<EntryEditFieldView, DateTimeEditView>(true)
}
override fun populateEntryInfoWithViews(templateFieldNotEmpty: Boolean) {
if (mEntryInfo == null)
mEntryInfo = EntryInfo()
// Icon already populate
val titleView: EntryEditFieldView? = findViewWithTag(FIELD_TITLE_TAG)
titleView?.value?.let {
mEntryInfo?.title = it
}
val userNameView: EntryEditFieldView? = templateContainerView.findViewWithTag(FIELD_USERNAME_TAG)
userNameView?.value?.let {
mEntryInfo?.username = it
}
val passwordView: EntryEditFieldView? = templateContainerView.findViewWithTag(FIELD_PASSWORD_TAG)
passwordView?.value?.let {
mEntryInfo?.password = it
}
val urlView: EntryEditFieldView? = templateContainerView.findViewWithTag(FIELD_URL_TAG)
urlView?.value?.let {
mEntryInfo?.url = it
}
val expirationView: DateTimeEditView? = templateContainerView.findViewWithTag(FIELD_EXPIRES_TAG)
expirationView?.activation?.let {
mEntryInfo?.expires = it
}
expirationView?.dateTime?.let {
mEntryInfo?.expiryTime = it
}
val notesView: EntryEditFieldView? = templateContainerView.findViewWithTag(FIELD_NOTES_TAG)
notesView?.value?.let {
mEntryInfo?.notes = it
}
retrieveCustomFieldsFromView(templateFieldNotEmpty)
populateSpecificEntryInfoWithViews<EntryEditFieldView, DateTimeEditView>(templateFieldNotEmpty)
mEntryInfo?.otpModel = OtpEntryFields.parseFields { key ->
getCustomField(key).protectedValue.toString()
}?.otpModel
@@ -325,8 +228,4 @@ class TemplateEditView @JvmOverloads constructor(context: Context,
override fun onSaveEntryInstanceState(savedState: SavedState) {
savedState.tempDateTimeViewId = this.mTempDateTimeViewId
}
companion object {
private val TAG = TemplateEditView::class.java.name
}
}

View File

@@ -2,7 +2,6 @@ package com.kunzisoft.keepass.view
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.View
import androidx.core.view.isVisible
import com.kunzisoft.keepass.R
@@ -12,7 +11,6 @@ import com.kunzisoft.keepass.database.element.security.ProtectedString
import com.kunzisoft.keepass.database.element.template.TemplateAttribute
import com.kunzisoft.keepass.database.element.template.TemplateAttributeType
import com.kunzisoft.keepass.database.element.template.TemplateField
import com.kunzisoft.keepass.model.EntryInfo
import com.kunzisoft.keepass.model.OtpModel
import com.kunzisoft.keepass.otp.OtpElement
import com.kunzisoft.keepass.otp.OtpEntryFields.OTP_TOKEN_FIELD
@@ -123,91 +121,15 @@ class TemplateView @JvmOverloads constructor(context: Context,
}
override fun populateViewsWithEntryInfo() {
mEntryInfo?.let { entryInfo ->
val titleView: EntryFieldView? =
findViewWithTag(FIELD_TITLE_TAG)
titleView?.value = entryInfo.title
titleView?.applyFontVisibility(mFontInVisibility)
if (entryInfo.title.isEmpty()) {
titleView?.isVisible = false
}
val userNameView: EntryFieldView? =
templateContainerView.findViewWithTag(FIELD_USERNAME_TAG)
userNameView?.value = entryInfo.username
userNameView?.applyFontVisibility(mFontInVisibility)
if (entryInfo.username.isEmpty()) {
userNameView?.isVisible = false
}
val passwordView: EntryFieldView? =
templateContainerView.findViewWithTag(FIELD_PASSWORD_TAG)
passwordView?.value = entryInfo.password
passwordView?.applyFontVisibility(mFontInVisibility)
if (entryInfo.password.isEmpty()) {
passwordView?.isVisible = false
}
val urlView: EntryFieldView? = templateContainerView.findViewWithTag(
FIELD_URL_TAG
)
urlView?.value = entryInfo.url
urlView?.applyFontVisibility(mFontInVisibility)
if (entryInfo.url.isEmpty()) {
urlView?.isVisible = false
}
val expirationView: DateTimeView? =
templateContainerView.findViewWithTag(FIELD_EXPIRES_TAG)
expirationView?.activation = entryInfo.expires
expirationView?.dateTime = entryInfo.expiryTime
if (!entryInfo.expires) {
expirationView?.isVisible = false
}
val notesView: EntryFieldView? =
templateContainerView.findViewWithTag(FIELD_NOTES_TAG)
notesView?.value = entryInfo.notes
notesView?.applyFontVisibility(mFontInVisibility)
if (entryInfo.notes.isEmpty()) {
notesView?.isVisible = false
}
customFieldsContainerView.removeAllViews()
val emptyCustomFields = mutableListOf<FieldId>().also { it.addAll(mCustomFieldIds) }
entryInfo.customFields.forEach { customField ->
val indexFieldViewId = indexCustomFieldIdByName(customField.name)
if (indexFieldViewId >= 0) {
// Template contains the custom view
val customFieldId = mCustomFieldIds[indexFieldViewId]
emptyCustomFields.remove(customFieldId)
templateContainerView.findViewById<View>(customFieldId.viewId)
?.let { customView ->
if (customView is EntryFieldView) {
customView.value = customField.protectedValue.stringValue
customView.applyFontVisibility(mFontInVisibility)
} else if (customView is DateTimeView) {
try {
customView.dateTime =
DateInstant(customField.protectedValue.stringValue)
} catch (e: Exception) {
Log.e(TAG, "unable to populate date time view", e)
}
}
}
} else {
// If template view not found, create a new custom view
putCustomField(customField, false)
}
}
populateSpecificViewsWithEntryInfo<EntryFieldView, DateTimeView>(false) { emptyCustomFields ->
// Hide empty custom fields
emptyCustomFields.forEach { customFieldId ->
templateContainerView.findViewById<View>(customFieldId.viewId)
.isVisible = false
}
}
mEntryInfo?.let { entryInfo ->
// Assign specific OTP dynamic view
removeOtpRunnable()
entryInfo.otpModel?.let {
@@ -217,45 +139,7 @@ class TemplateView @JvmOverloads constructor(context: Context,
}
override fun populateEntryInfoWithViews(templateFieldNotEmpty: Boolean) {
if (mEntryInfo == null)
mEntryInfo = EntryInfo()
// Icon already populate
val titleView: EntryFieldView? = findViewWithTag(FIELD_TITLE_TAG)
titleView?.value?.let {
mEntryInfo?.title = it
}
val userNameView: EntryFieldView? = templateContainerView.findViewWithTag(FIELD_USERNAME_TAG)
userNameView?.value?.let {
mEntryInfo?.username = it
}
val passwordView: EntryFieldView? = templateContainerView.findViewWithTag(FIELD_PASSWORD_TAG)
passwordView?.value?.let {
mEntryInfo?.password = it
}
val urlView: EntryFieldView? = templateContainerView.findViewWithTag(FIELD_URL_TAG)
urlView?.value?.let {
mEntryInfo?.url = it
}
val expirationView: DateTimeView? = templateContainerView.findViewWithTag(FIELD_EXPIRES_TAG)
expirationView?.activation?.let {
mEntryInfo?.expires = it
}
expirationView?.dateTime?.let {
mEntryInfo?.expiryTime = it
}
val notesView: EntryFieldView? = templateContainerView.findViewWithTag(FIELD_NOTES_TAG)
notesView?.value?.let {
mEntryInfo?.notes = it
}
retrieveCustomFieldsFromView(templateFieldNotEmpty)
populateSpecificEntryInfoWithViews<EntryFieldView, DateTimeView>(templateFieldNotEmpty)
}
override fun getCustomField(fieldName: String, templateFieldNotEmpty: Boolean): Field? {
@@ -339,8 +223,4 @@ class TemplateView @JvmOverloads constructor(context: Context,
mLastOtpTokenView?.removeCallbacks(mOtpRunnable)
mLastOtpTokenView = null
}
companion object {
private val TAG = TemplateEditView::class.java.name
}
}

View File

@@ -62,16 +62,24 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/entry_edit_header_container"
app:layout_constraintBottom_toTopOf="@+id/custom_fields_container"
app:layout_constraintBottom_toTopOf="@+id/not_referenced_fields_container"
android:orientation="vertical" />
<com.kunzisoft.keepass.view.SectionView
android:id="@+id/not_referenced_fields_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?attr/cardViewStyle"
android:layout_marginBottom="@dimen/card_view_margin_vertical"
app:layout_constraintTop_toBottomOf="@+id/template_fields_container"
app:layout_constraintBottom_toTopOf="@+id/custom_fields_container"/>
<com.kunzisoft.keepass.view.SectionView
android:id="@+id/custom_fields_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?attr/cardViewStyle"
android:layout_marginBottom="@dimen/card_view_margin_vertical"
app:layout_constraintTop_toBottomOf="@+id/template_fields_container"
app:layout_constraintTop_toBottomOf="@+id/not_referenced_fields_container"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>