Encapsulate username and OTP as EntryField

This commit is contained in:
J-Jamet
2020-08-21 18:35:54 +02:00
parent 46c259bc3e
commit 5d7db046ac
4 changed files with 51 additions and 134 deletions

View File

@@ -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)
})
}
)
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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>