mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Encapsulate username and OTP as EntryField
This commit is contained in:
@@ -430,28 +430,31 @@ class EntryActivity : LockingActivity() {
|
||||
|
||||
private fun performedNextEducation(entryActivityEducation: EntryActivityEducation,
|
||||
menu: Menu) {
|
||||
val entryCopyEducationPerformed = entryContentsView?.isUserNamePresent == true
|
||||
val entryFieldCopyView = findViewById<View>(R.id.entry_field_copy)
|
||||
val entryCopyEducationPerformed = entryFieldCopyView != null
|
||||
&& entryActivityEducation.checkAndPerformedEntryCopyEducation(
|
||||
findViewById(R.id.entry_user_name_action_image),
|
||||
entryFieldCopyView,
|
||||
{
|
||||
clipboardHelper?.timeoutCopyToClipboard(mEntry!!.username,
|
||||
getString(R.string.copy_field,
|
||||
getString(R.string.entry_user_name)))
|
||||
val appNameString = getString(R.string.app_name)
|
||||
clipboardHelper?.timeoutCopyToClipboard(appNameString,
|
||||
getString(R.string.copy_field, appNameString))
|
||||
},
|
||||
{
|
||||
performedNextEducation(entryActivityEducation, menu)
|
||||
})
|
||||
|
||||
if (!entryCopyEducationPerformed) {
|
||||
val menuEditView = toolbar?.findViewById<View>(R.id.menu_edit)
|
||||
// entryEditEducationPerformed
|
||||
toolbar?.findViewById<View>(R.id.menu_edit) != null && entryActivityEducation.checkAndPerformedEntryEditEducation(
|
||||
toolbar!!.findViewById(R.id.menu_edit),
|
||||
menuEditView != null && entryActivityEducation.checkAndPerformedEntryEditEducation(
|
||||
menuEditView,
|
||||
{
|
||||
onOptionsItemSelected(menu.findItem(R.id.menu_edit))
|
||||
},
|
||||
{
|
||||
performedNextEducation(entryActivityEducation, menu)
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator
|
||||
@@ -52,16 +51,9 @@ class EntryContentsView @JvmOverloads constructor(context: Context,
|
||||
|
||||
private var fontInVisibility: Boolean = false
|
||||
|
||||
private val userNameContainerView: View
|
||||
private val userNameView: TextView
|
||||
private val userNameActionView: ImageView
|
||||
|
||||
private val userNameFieldView: EntryField
|
||||
private val passwordFieldView: EntryField
|
||||
|
||||
private val otpContainerView: View
|
||||
private val otpLabelView: TextView
|
||||
private val otpView: TextView
|
||||
private val otpActionView: ImageView
|
||||
private val otpFieldView: EntryField
|
||||
|
||||
private var otpRunnable: Runnable? = null
|
||||
|
||||
@@ -91,27 +83,18 @@ class EntryContentsView @JvmOverloads constructor(context: Context,
|
||||
private val uuidView: TextView
|
||||
private val uuidReferenceView: TextView
|
||||
|
||||
val isUserNamePresent: Boolean
|
||||
get() = userNameContainerView.visibility == View.VISIBLE
|
||||
|
||||
val isPasswordPresent: Boolean
|
||||
get() = passwordFieldView.visibility == View.VISIBLE
|
||||
|
||||
init {
|
||||
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater?
|
||||
inflater?.inflate(R.layout.view_entry_contents, this)
|
||||
|
||||
userNameContainerView = findViewById(R.id.entry_user_name_container)
|
||||
userNameView = findViewById(R.id.entry_user_name)
|
||||
userNameActionView = findViewById(R.id.entry_user_name_action_image)
|
||||
userNameFieldView = findViewById(R.id.entry_user_name_field)
|
||||
userNameFieldView.setLabel(R.string.entry_user_name)
|
||||
|
||||
passwordFieldView = findViewById(R.id.entry_password_field)
|
||||
passwordFieldView.setLabel(R.string.password)
|
||||
|
||||
otpContainerView = findViewById(R.id.entry_otp_container)
|
||||
otpLabelView = findViewById(R.id.entry_otp_label)
|
||||
otpView = findViewById(R.id.entry_otp)
|
||||
otpActionView = findViewById(R.id.entry_otp_action_image)
|
||||
otpFieldView = findViewById(R.id.entry_otp_field)
|
||||
otpFieldView.setLabel(R.string.entry_otp)
|
||||
|
||||
urlContainerView = findViewById(R.id.entry_url_container)
|
||||
urlView = findViewById(R.id.entry_url)
|
||||
@@ -153,19 +136,18 @@ class EntryContentsView @JvmOverloads constructor(context: Context,
|
||||
|
||||
fun assignUserName(userName: String?) {
|
||||
if (userName != null && userName.isNotEmpty()) {
|
||||
userNameContainerView.visibility = View.VISIBLE
|
||||
userNameView.apply {
|
||||
text = userName
|
||||
if (fontInVisibility)
|
||||
applyFontVisibility()
|
||||
userNameFieldView.apply {
|
||||
visibility = View.VISIBLE
|
||||
setValue(userName)
|
||||
applyFontVisibility(fontInVisibility)
|
||||
}
|
||||
} else {
|
||||
userNameContainerView.visibility = View.GONE
|
||||
userNameFieldView.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
fun assignUserNameCopyListener(onClickListener: OnClickListener) {
|
||||
userNameActionView.setOnClickListener(onClickListener)
|
||||
userNameFieldView.assignCopyButtonClickListener(onClickListener)
|
||||
}
|
||||
|
||||
fun assignPassword(password: String?, allowCopyPassword: Boolean) {
|
||||
@@ -185,18 +167,6 @@ class EntryContentsView @JvmOverloads constructor(context: Context,
|
||||
passwordFieldView.assignCopyButtonClickListener(onClickListener)
|
||||
}
|
||||
|
||||
fun atLeastOneFieldProtectedPresent(): Boolean {
|
||||
extraFieldsListView.let {
|
||||
for (i in 0 until it.childCount) {
|
||||
val childCustomView = it.getChildAt(i)
|
||||
if (childCustomView is EntryField)
|
||||
if (childCustomView.isProtected)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun setHiddenProtectedValue(hiddenProtectedValue: Boolean) {
|
||||
passwordFieldView.hiddenProtectedValue = hiddenProtectedValue
|
||||
// Hidden style for custom fields
|
||||
@@ -212,19 +182,19 @@ class EntryContentsView @JvmOverloads constructor(context: Context,
|
||||
fun assignOtp(otpElement: OtpElement?,
|
||||
otpProgressView: ProgressBar?,
|
||||
onClickListener: OnClickListener) {
|
||||
otpContainerView.removeCallbacks(otpRunnable)
|
||||
otpFieldView.removeCallbacks(otpRunnable)
|
||||
|
||||
if (otpElement != null) {
|
||||
otpContainerView.visibility = View.VISIBLE
|
||||
otpFieldView.visibility = View.VISIBLE
|
||||
|
||||
if (otpElement.token.isEmpty()) {
|
||||
otpView.text = context.getString(R.string.error_invalid_OTP)
|
||||
otpActionView.setColorFilter(ContextCompat.getColor(context, R.color.grey_dark))
|
||||
assignOtpCopyListener(null)
|
||||
otpFieldView.setValue(R.string.error_invalid_OTP)
|
||||
otpFieldView.activateCopyButton(false)
|
||||
otpFieldView.assignCopyButtonClickListener(null)
|
||||
} else {
|
||||
assignOtpCopyListener(onClickListener)
|
||||
otpView.text = otpElement.token
|
||||
otpLabelView.text = otpElement.type.name
|
||||
otpFieldView.setLabel(otpElement.type.name)
|
||||
otpFieldView.setValue(otpElement.token)
|
||||
otpFieldView.assignCopyButtonClickListener(onClickListener)
|
||||
|
||||
when (otpElement.type) {
|
||||
// Only add token if HOTP
|
||||
@@ -240,25 +210,21 @@ class EntryContentsView @JvmOverloads constructor(context: Context,
|
||||
}
|
||||
otpRunnable = Runnable {
|
||||
if (otpElement.shouldRefreshToken()) {
|
||||
otpView.text = otpElement.token
|
||||
otpFieldView.setValue(otpElement.token)
|
||||
}
|
||||
otpProgressView?.progress = otpElement.secondsRemaining
|
||||
otpContainerView.postDelayed(otpRunnable, 1000)
|
||||
otpFieldView.postDelayed(otpRunnable, 1000)
|
||||
}
|
||||
otpContainerView.post(otpRunnable)
|
||||
otpFieldView.post(otpRunnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
otpContainerView.visibility = View.GONE
|
||||
otpFieldView.visibility = View.GONE
|
||||
otpProgressView?.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
fun assignOtpCopyListener(onClickListener: OnClickListener?) {
|
||||
otpActionView.setOnClickListener(onClickListener)
|
||||
}
|
||||
|
||||
fun assignURL(url: String?) {
|
||||
if (url != null && url.isNotEmpty()) {
|
||||
urlContainerView.visibility = View.VISIBLE
|
||||
|
||||
@@ -83,6 +83,10 @@ class EntryField @JvmOverloads constructor(context: Context,
|
||||
valueView.applyHiddenStyle(isProtected && !showButtonView.isSelected)
|
||||
}
|
||||
|
||||
fun setValue(@StringRes valueId: Int, isProtected: Boolean = false) {
|
||||
setValue(resources.getString(valueId), isProtected)
|
||||
}
|
||||
|
||||
fun activateCopyButton(enable: Boolean) {
|
||||
// Reverse because isActivated show custom color and allow click
|
||||
copyButtonView.isActivated = !enable
|
||||
|
||||
@@ -40,39 +40,11 @@
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Username -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/entry_user_name_container"
|
||||
<com.kunzisoft.keepass.view.EntryField
|
||||
android:id="@+id/entry_user_name_field"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone">
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/entry_user_name_label"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/entry_user_name_action_image"
|
||||
android:text="@string/entry_user_name"
|
||||
style="@style/KeepassDXStyle.TextAppearance.LabelTextStyle" />
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/entry_user_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@+id/entry_user_name_label"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/entry_user_name_action_image"
|
||||
android:textIsSelectable="true"
|
||||
style="@style/KeepassDXStyle.TextAppearance.TextEntryItem" />
|
||||
<androidx.appcompat.widget.AppCompatImageButton
|
||||
android:id="@+id/entry_user_name_action_image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:src="@drawable/ic_content_copy_white_24dp"
|
||||
android:contentDescription="@string/menu_copy"
|
||||
style="@style/KeepassDXStyle.ImageButton.Simple" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- Password -->
|
||||
<com.kunzisoft.keepass.view.EntryField
|
||||
@@ -82,39 +54,11 @@
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- OTP -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/entry_otp_container"
|
||||
<com.kunzisoft.keepass.view.EntryField
|
||||
android:id="@+id/entry_otp_field"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone">
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/entry_otp_label"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/entry_otp_action_image"
|
||||
android:text="@string/entry_otp"
|
||||
style="@style/KeepassDXStyle.TextAppearance.LabelTextStyle" />
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/entry_otp"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@+id/entry_otp_label"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/entry_otp_action_image"
|
||||
android:textIsSelectable="true"
|
||||
style="@style/KeepassDXStyle.TextAppearance.TextEntryItem" />
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/entry_otp_action_image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:src="@drawable/ic_content_copy_white_24dp"
|
||||
android:contentDescription="@string/menu_copy"
|
||||
style="@style/KeepassDXStyle.ImageButton.Simple" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- URL -->
|
||||
<LinearLayout
|
||||
@@ -150,13 +94,13 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/entry_notes"
|
||||
android:autoLink="all"
|
||||
style="@style/KeepassDXStyle.TextAppearance.LabelTextStyle" />
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/entry_notes"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textIsSelectable="true"
|
||||
android:autoLink="all"
|
||||
style="@style/KeepassDXStyle.TextAppearance.TextEntryItem" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
Reference in New Issue
Block a user