mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Fix OTP runnable
This commit is contained in:
@@ -182,7 +182,9 @@ class EntryActivity : LockingActivity() {
|
||||
}
|
||||
|
||||
mEntryViewModel.onOtpElementUpdated.observe(this) { otpElement ->
|
||||
when (otpElement.type) {
|
||||
if (otpElement == null)
|
||||
entryProgress?.visibility = View.GONE
|
||||
when (otpElement?.type) {
|
||||
// Only add token if HOTP
|
||||
OtpType.HOTP -> {
|
||||
entryProgress?.visibility = View.GONE
|
||||
|
||||
@@ -46,7 +46,6 @@ class EntryFragment: DatabaseFragment() {
|
||||
private lateinit var uuidView: TextView
|
||||
private lateinit var uuidReferenceView: TextView
|
||||
|
||||
private var mOtpRunnable: Runnable? = null
|
||||
private var mClipboardHelper: ClipboardHelper? = null
|
||||
|
||||
private val mEntryViewModel: EntryViewModel by activityViewModels()
|
||||
@@ -143,8 +142,10 @@ class EntryFragment: DatabaseFragment() {
|
||||
// Populate entry views
|
||||
templateView.setEntryInfo(entryInfo)
|
||||
|
||||
//Assign OTP field
|
||||
assignOtp(entryInfo)
|
||||
// OTP timer updated
|
||||
templateView.setOnOtpElementUpdated { otpElementUpdated ->
|
||||
mEntryViewModel.onOtpElementUpdated(otpElementUpdated)
|
||||
}
|
||||
|
||||
// Manage attachments
|
||||
assignAttachments(entryInfo?.attachments ?: listOf())
|
||||
@@ -185,39 +186,6 @@ class EntryFragment: DatabaseFragment() {
|
||||
templateView.reload()
|
||||
}
|
||||
|
||||
private fun assignOtp(entryInfo: EntryInfo?) {
|
||||
entryInfo?.otpModel?.let { otpModel ->
|
||||
val otpElement = OtpElement(otpModel)
|
||||
templateView.getOtpTokenView()?.let { otpFieldView ->
|
||||
otpFieldView.removeCallbacks(mOtpRunnable)
|
||||
if (otpElement.token.isEmpty()) {
|
||||
otpFieldView.setLabel(R.string.entry_otp)
|
||||
otpFieldView.setValue(R.string.error_invalid_OTP)
|
||||
otpFieldView.setCopyButtonState(EntryFieldView.ButtonState.GONE)
|
||||
} else {
|
||||
otpFieldView.label = otpElement.type.name
|
||||
otpFieldView.value = otpElement.token
|
||||
otpFieldView.setCopyButtonState(EntryFieldView.ButtonState.ACTIVATE)
|
||||
otpFieldView.setCopyButtonClickListener {
|
||||
mClipboardHelper?.timeoutCopyToClipboard(
|
||||
otpElement.token,
|
||||
getString(R.string.copy_field, getString(R.string.entry_otp))
|
||||
)
|
||||
}
|
||||
mOtpRunnable = Runnable {
|
||||
if (otpElement.shouldRefreshToken()) {
|
||||
otpFieldView.value = otpElement.token
|
||||
}
|
||||
mEntryViewModel.onOtpElementUpdated(otpElement)
|
||||
otpFieldView.postDelayed(mOtpRunnable, 1000)
|
||||
}
|
||||
mEntryViewModel.onOtpElementUpdated(otpElement)
|
||||
otpFieldView.post(mOtpRunnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignCreationDate(date: DateInstant?) {
|
||||
creationDateView.text = date?.getDateTimeString(resources)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.core.view.isVisible
|
||||
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.security.ProtectedString
|
||||
@@ -12,7 +13,8 @@ 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.otp.OtpEntryFields
|
||||
import com.kunzisoft.keepass.model.OtpModel
|
||||
import com.kunzisoft.keepass.otp.OtpElement
|
||||
import com.kunzisoft.keepass.otp.OtpEntryFields.OTP_TOKEN_FIELD
|
||||
|
||||
|
||||
@@ -205,6 +207,12 @@ class TemplateView @JvmOverloads constructor(context: Context,
|
||||
templateContainerView.findViewById<View>(customFieldId.viewId)
|
||||
.isVisible = false
|
||||
}
|
||||
|
||||
// Assign specific OTP dynamic view
|
||||
removeOtpRunnable()
|
||||
entryInfo.otpModel?.let {
|
||||
assignOtp(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,20 +256,6 @@ class TemplateView @JvmOverloads constructor(context: Context,
|
||||
}
|
||||
|
||||
retrieveCustomFieldsFromView(templateFieldNotEmpty)
|
||||
|
||||
mEntryInfo?.otpModel = OtpEntryFields.parseFields { key ->
|
||||
getCustomField(key).protectedValue.toString()
|
||||
}?.otpModel
|
||||
}
|
||||
|
||||
fun getOtpTokenView(): EntryFieldView? {
|
||||
val indexFieldViewId = indexCustomFieldIdByName(OTP_TOKEN_FIELD)
|
||||
if (indexFieldViewId >= 0) {
|
||||
// Template contains the custom view
|
||||
val customFieldId = mCustomFieldIds[indexFieldViewId]
|
||||
return findViewById(customFieldId.viewId)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getCustomField(fieldName: String, templateFieldNotEmpty: Boolean): Field? {
|
||||
@@ -285,6 +279,67 @@ class TemplateView @JvmOverloads constructor(context: Context,
|
||||
return null
|
||||
}
|
||||
|
||||
/*
|
||||
* OTP Runnable
|
||||
*/
|
||||
|
||||
private var mOtpRunnable: Runnable? = null
|
||||
private var mLastOtpTokenView: View? = null
|
||||
|
||||
fun setOnOtpElementUpdated(listener: ((OtpElement?) -> Unit)?) {
|
||||
this.mOnOtpElementUpdated = listener
|
||||
}
|
||||
private var mOnOtpElementUpdated: ((OtpElement?) -> Unit)? = null
|
||||
|
||||
private fun getOtpTokenView(): EntryFieldView? {
|
||||
val indexFieldViewId = indexCustomFieldIdByName(OTP_TOKEN_FIELD)
|
||||
if (indexFieldViewId >= 0) {
|
||||
// Template contains the custom view
|
||||
val customFieldId = mCustomFieldIds[indexFieldViewId]
|
||||
return findViewById(customFieldId.viewId)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun assignOtp(otpModel: OtpModel) {
|
||||
getOtpTokenView()?.apply {
|
||||
val otpElement = OtpElement(otpModel)
|
||||
if (otpElement.token.isEmpty()) {
|
||||
setLabel(R.string.entry_otp)
|
||||
setValue(R.string.error_invalid_OTP)
|
||||
setCopyButtonState(EntryFieldView.ButtonState.GONE)
|
||||
} else {
|
||||
label = otpElement.type.name
|
||||
value = otpElement.token
|
||||
setCopyButtonState(EntryFieldView.ButtonState.ACTIVATE)
|
||||
setCopyButtonClickListener {
|
||||
mOnCopyActionClickListener?.invoke(Field(
|
||||
otpElement.type.name,
|
||||
ProtectedString(false, otpElement.token)))
|
||||
}
|
||||
mLastOtpTokenView = this
|
||||
mOtpRunnable = Runnable {
|
||||
if (otpElement.shouldRefreshToken()) {
|
||||
value = otpElement.token
|
||||
}
|
||||
if (mLastOtpTokenView == null) {
|
||||
mOnOtpElementUpdated?.invoke(null)
|
||||
} else {
|
||||
mOnOtpElementUpdated?.invoke(otpElement)
|
||||
postDelayed(mOtpRunnable, 1000)
|
||||
}
|
||||
}
|
||||
mOnOtpElementUpdated?.invoke(otpElement)
|
||||
post(mOtpRunnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeOtpRunnable() {
|
||||
mLastOtpTokenView?.removeCallbacks(mOtpRunnable)
|
||||
mLastOtpTokenView = null
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = TemplateEditView::class.java.name
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ class EntryViewModel: ViewModel() {
|
||||
val entryHistory : LiveData<List<EntryInfo>> get() = _entryHistory
|
||||
private val _entryHistory = MutableLiveData<List<EntryInfo>>()
|
||||
|
||||
val onOtpElementUpdated : LiveData<OtpElement> get() = _onOtpElementUpdated
|
||||
private val _onOtpElementUpdated = SingleLiveEvent<OtpElement>()
|
||||
val onOtpElementUpdated : LiveData<OtpElement?> get() = _onOtpElementUpdated
|
||||
private val _onOtpElementUpdated = SingleLiveEvent<OtpElement?>()
|
||||
|
||||
val attachmentSelected : LiveData<Attachment> get() = _attachmentSelected
|
||||
private val _attachmentSelected = SingleLiveEvent<Attachment>()
|
||||
@@ -122,7 +122,7 @@ class EntryViewModel: ViewModel() {
|
||||
return entryIsHistory.value ?: false
|
||||
}
|
||||
|
||||
fun onOtpElementUpdated(optElement: OtpElement) {
|
||||
fun onOtpElementUpdated(optElement: OtpElement?) {
|
||||
_onOtpElementUpdated.value = optElement
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user