mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Fix custom field creation
This commit is contained in:
@@ -124,8 +124,7 @@
|
||||
android:configChanges="keyboardHidden" />
|
||||
<activity
|
||||
android:name="com.kunzisoft.keepass.activities.EntryEditActivity"
|
||||
android:configChanges="keyboardHidden"
|
||||
android:windowSoftInputMode="adjustPan" />
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
<!-- About and Settings -->
|
||||
<activity
|
||||
android:name="com.kunzisoft.keepass.activities.AboutActivity"
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.util.Log
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.widget.DatePicker
|
||||
import android.widget.TimePicker
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
@@ -353,15 +354,19 @@ class EntryEditActivity : LockingActivity(),
|
||||
EntryCustomFieldDialogFragment.getInstance().show(supportFragmentManager, "customFieldDialog")
|
||||
}
|
||||
|
||||
override fun onNewCustomFieldApproved(label: String, name: ProtectedString) {
|
||||
entryEditContentsView?.putCustomField(label, name)
|
||||
scrollView?.postDelayed({
|
||||
override fun onNewCustomFieldApproved(label: String) {
|
||||
val customFieldView = entryEditContentsView?.putCustomField(label, ProtectedString())
|
||||
window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
|
||||
scrollView?.post {
|
||||
//scrollView?.smoothScrollTo(0, customFieldView.bottom)
|
||||
scrollView?.fullScroll(View.FOCUS_DOWN)
|
||||
entryEditContentsView?.focusLastChild()
|
||||
}, 500)
|
||||
customFieldView?.post {
|
||||
customFieldView.requestFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNewCustomFieldCanceled(label: String, name: ProtectedString) {}
|
||||
override fun onNewCustomFieldCanceled(label: String) {}
|
||||
|
||||
private fun setupOTP() {
|
||||
// Retrieve the current otpElement if exists
|
||||
|
||||
@@ -22,15 +22,16 @@ package com.kunzisoft.keepass.activities.dialogs
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.Button
|
||||
import android.widget.CompoundButton
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.security.ProtectedString
|
||||
|
||||
|
||||
class EntryCustomFieldDialogFragment: DialogFragment() {
|
||||
|
||||
@@ -38,8 +39,6 @@ class EntryCustomFieldDialogFragment: DialogFragment() {
|
||||
|
||||
private var newFieldLabelContainer: TextInputLayout? = null
|
||||
private var newFieldLabel: TextView? = null
|
||||
private var newFieldValue: TextView? = null
|
||||
private var newFieldProtection: CompoundButton? = null
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
@@ -57,23 +56,29 @@ class EntryCustomFieldDialogFragment: DialogFragment() {
|
||||
val root = activity.layoutInflater.inflate(R.layout.fragment_entry_new_field, null)
|
||||
newFieldLabelContainer = root?.findViewById(R.id.new_field_label_container)
|
||||
newFieldLabel = root?.findViewById(R.id.new_field_label)
|
||||
newFieldValue = root?.findViewById(R.id.new_field_value)
|
||||
newFieldProtection = root?.findViewById(R.id.new_field_protection)
|
||||
|
||||
val builder = AlertDialog.Builder(activity)
|
||||
builder.setView(root)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ ->
|
||||
entryCustomFieldListener?.onNewCustomFieldCanceled(
|
||||
newFieldLabel?.text.toString(),
|
||||
ProtectedString(
|
||||
newFieldProtection?.isChecked == true,
|
||||
newFieldValue?.text.toString()
|
||||
)
|
||||
newFieldLabel?.text.toString()
|
||||
)
|
||||
}
|
||||
val dialogCreated = builder.create()
|
||||
|
||||
newFieldLabel?.requestFocus()
|
||||
newFieldLabel?.imeOptions = EditorInfo.IME_ACTION_DONE
|
||||
newFieldLabel?.setOnEditorActionListener { _, actionId, _ ->
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
approveIfValid()
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
dialogCreated.window?.setSoftInputMode(SOFT_INPUT_STATE_VISIBLE)
|
||||
return dialogCreated
|
||||
|
||||
return builder.create()
|
||||
}
|
||||
return super.onCreateDialog(savedInstanceState)
|
||||
}
|
||||
@@ -86,20 +91,20 @@ class EntryCustomFieldDialogFragment: DialogFragment() {
|
||||
if (d != null) {
|
||||
val positiveButton = d.getButton(Dialog.BUTTON_POSITIVE) as Button
|
||||
positiveButton.setOnClickListener {
|
||||
if (isValid()) {
|
||||
entryCustomFieldListener?.onNewCustomFieldApproved(
|
||||
newFieldLabel?.text.toString(),
|
||||
ProtectedString(
|
||||
newFieldProtection?.isChecked == true,
|
||||
newFieldValue?.text.toString()
|
||||
)
|
||||
)
|
||||
d.dismiss()
|
||||
}
|
||||
approveIfValid()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun approveIfValid() {
|
||||
if (isValid()) {
|
||||
entryCustomFieldListener?.onNewCustomFieldApproved(
|
||||
newFieldLabel?.text.toString()
|
||||
)
|
||||
(dialog as AlertDialog?)?.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun isValid(): Boolean {
|
||||
return if (newFieldLabel?.text?.toString()?.isNotEmpty() != true) {
|
||||
setError(R.string.error_string_key)
|
||||
@@ -117,8 +122,8 @@ class EntryCustomFieldDialogFragment: DialogFragment() {
|
||||
}
|
||||
|
||||
interface EntryCustomFieldListener {
|
||||
fun onNewCustomFieldApproved(label: String, name: ProtectedString)
|
||||
fun onNewCustomFieldCanceled(label: String, name: ProtectedString)
|
||||
fun onNewCustomFieldApproved(label: String)
|
||||
fun onNewCustomFieldCanceled(label: String)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -215,35 +215,36 @@ class EntryEditContentsView @JvmOverloads constructor(context: Context,
|
||||
return customFieldsArray
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a custom field or create a new one if doesn't exists
|
||||
*/
|
||||
fun putCustomField(name: String,
|
||||
value: ProtectedString = ProtectedString()) {
|
||||
var updateField = false
|
||||
private fun getCustomFieldByLabel(label: String): EntryEditCustomField? {
|
||||
for (i in 0..entryExtraFieldsContainer.childCount) {
|
||||
try {
|
||||
val extraFieldView = entryExtraFieldsContainer.getChildAt(i) as EntryEditCustomField?
|
||||
if (extraFieldView?.label == name) {
|
||||
extraFieldView.setData(name, value, fontInVisibility)
|
||||
updateField = true
|
||||
break
|
||||
if (extraFieldView?.label == label) {
|
||||
return extraFieldView
|
||||
}
|
||||
} catch(e: Exception) {
|
||||
// Simply ignore when child view is not a custom field
|
||||
}
|
||||
}
|
||||
if (!updateField) {
|
||||
val entryEditCustomField = EntryEditCustomField(context).apply {
|
||||
setData(name, value, fontInVisibility)
|
||||
}
|
||||
entryExtraFieldsContainer.addView(entryEditCustomField)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun focusLastChild() {
|
||||
val lastChildNumber = entryExtraFieldsContainer.childCount - 1
|
||||
entryExtraFieldsContainer.getChildAt(lastChildNumber).requestFocus()
|
||||
/**
|
||||
* Update a custom field or create a new one if doesn't exists
|
||||
*/
|
||||
fun putCustomField(name: String,
|
||||
value: ProtectedString = ProtectedString())
|
||||
: EntryEditCustomField {
|
||||
var extraFieldView = getCustomFieldByLabel(name)
|
||||
extraFieldView?.setData(name, value, fontInVisibility)
|
||||
// Create new view if not exists
|
||||
if (extraFieldView == null) {
|
||||
extraFieldView = EntryEditCustomField(context).apply {
|
||||
setData(name, value, fontInVisibility)
|
||||
}
|
||||
entryExtraFieldsContainer.addView(extraFieldView)
|
||||
}
|
||||
return extraFieldView
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,63 +18,27 @@
|
||||
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<RelativeLayout
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/new_field_label_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:importantForAutofill="noExcludeDescendants"
|
||||
tools:targetApi="o">
|
||||
android:paddingTop="@dimen/default_margin"
|
||||
android:paddingLeft="@dimen/default_margin"
|
||||
android:paddingStart="@dimen/default_margin"
|
||||
android:paddingRight="@dimen/default_margin"
|
||||
android:paddingEnd="@dimen/default_margin"
|
||||
tools:ignore="UnusedAttribute">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/new_field_label_container"
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/new_field_label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingLeft="@dimen/default_margin"
|
||||
android:paddingStart="@dimen/default_margin"
|
||||
android:paddingRight="@dimen/default_margin"
|
||||
android:paddingEnd="@dimen/default_margin">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/new_field_label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/field_name"
|
||||
android:importantForAccessibility="no"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="text"
|
||||
android:maxLines="1" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/new_field_value_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/default_margin"
|
||||
android:paddingStart="@dimen/default_margin"
|
||||
android:paddingRight="@dimen/default_margin"
|
||||
android:paddingEnd="@dimen/default_margin"
|
||||
android:layout_below="@+id/new_field_label_container">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/new_field_value"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textMultiLine"
|
||||
android:importantForAccessibility="no"
|
||||
android:importantForAutofill="no"
|
||||
android:hint="@string/field_value" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:id="@+id/new_field_protection"
|
||||
style="@style/KeepassDXStyle.TextAppearance.Small"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp"
|
||||
android:layout_below="@+id/new_field_value_container"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:text="@string/protection" />
|
||||
|
||||
</RelativeLayout>
|
||||
android:hint="@string/field_name"
|
||||
android:importantForAccessibility="no"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="text"
|
||||
android:maxLines="1" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
@@ -75,13 +75,13 @@
|
||||
style="@style/KeepassDXStyle.TextAppearance.Small"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp"
|
||||
android:layout_marginTop="@dimen/default_margin"
|
||||
android:minHeight="24dp"
|
||||
android:layout_marginStart="@dimen/default_margin"
|
||||
android:layout_marginLeft="@dimen/default_margin"
|
||||
android:layout_marginEnd="@dimen/default_margin"
|
||||
android:layout_marginRight="@dimen/default_margin"
|
||||
app:layout_constraintTop_toBottomOf="@+id/entry_new_field_delete"
|
||||
android:paddingBottom="@dimen/default_margin"
|
||||
app:layout_constraintTop_toBottomOf="@+id/new_field_value_container"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:text="@string/protection" />
|
||||
|
||||
Reference in New Issue
Block a user