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 ->
|
mEntryViewModel.onOtpElementUpdated.observe(this) { otpElement ->
|
||||||
when (otpElement.type) {
|
if (otpElement == null)
|
||||||
|
entryProgress?.visibility = View.GONE
|
||||||
|
when (otpElement?.type) {
|
||||||
// Only add token if HOTP
|
// Only add token if HOTP
|
||||||
OtpType.HOTP -> {
|
OtpType.HOTP -> {
|
||||||
entryProgress?.visibility = View.GONE
|
entryProgress?.visibility = View.GONE
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ class EntryFragment: DatabaseFragment() {
|
|||||||
private lateinit var uuidView: TextView
|
private lateinit var uuidView: TextView
|
||||||
private lateinit var uuidReferenceView: TextView
|
private lateinit var uuidReferenceView: TextView
|
||||||
|
|
||||||
private var mOtpRunnable: Runnable? = null
|
|
||||||
private var mClipboardHelper: ClipboardHelper? = null
|
private var mClipboardHelper: ClipboardHelper? = null
|
||||||
|
|
||||||
private val mEntryViewModel: EntryViewModel by activityViewModels()
|
private val mEntryViewModel: EntryViewModel by activityViewModels()
|
||||||
@@ -143,8 +142,10 @@ class EntryFragment: DatabaseFragment() {
|
|||||||
// Populate entry views
|
// Populate entry views
|
||||||
templateView.setEntryInfo(entryInfo)
|
templateView.setEntryInfo(entryInfo)
|
||||||
|
|
||||||
//Assign OTP field
|
// OTP timer updated
|
||||||
assignOtp(entryInfo)
|
templateView.setOnOtpElementUpdated { otpElementUpdated ->
|
||||||
|
mEntryViewModel.onOtpElementUpdated(otpElementUpdated)
|
||||||
|
}
|
||||||
|
|
||||||
// Manage attachments
|
// Manage attachments
|
||||||
assignAttachments(entryInfo?.attachments ?: listOf())
|
assignAttachments(entryInfo?.attachments ?: listOf())
|
||||||
@@ -185,39 +186,6 @@ class EntryFragment: DatabaseFragment() {
|
|||||||
templateView.reload()
|
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?) {
|
private fun assignCreationDate(date: DateInstant?) {
|
||||||
creationDateView.text = date?.getDateTimeString(resources)
|
creationDateView.text = date?.getDateTimeString(resources)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import android.util.AttributeSet
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import com.kunzisoft.keepass.R
|
||||||
import com.kunzisoft.keepass.database.element.DateInstant
|
import com.kunzisoft.keepass.database.element.DateInstant
|
||||||
import com.kunzisoft.keepass.database.element.Field
|
import com.kunzisoft.keepass.database.element.Field
|
||||||
import com.kunzisoft.keepass.database.element.security.ProtectedString
|
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.TemplateAttributeType
|
||||||
import com.kunzisoft.keepass.database.element.template.TemplateField
|
import com.kunzisoft.keepass.database.element.template.TemplateField
|
||||||
import com.kunzisoft.keepass.model.EntryInfo
|
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
|
import com.kunzisoft.keepass.otp.OtpEntryFields.OTP_TOKEN_FIELD
|
||||||
|
|
||||||
|
|
||||||
@@ -205,6 +207,12 @@ class TemplateView @JvmOverloads constructor(context: Context,
|
|||||||
templateContainerView.findViewById<View>(customFieldId.viewId)
|
templateContainerView.findViewById<View>(customFieldId.viewId)
|
||||||
.isVisible = false
|
.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)
|
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? {
|
override fun getCustomField(fieldName: String, templateFieldNotEmpty: Boolean): Field? {
|
||||||
@@ -285,6 +279,67 @@ class TemplateView @JvmOverloads constructor(context: Context,
|
|||||||
return null
|
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 {
|
companion object {
|
||||||
private val TAG = TemplateEditView::class.java.name
|
private val TAG = TemplateEditView::class.java.name
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ class EntryViewModel: ViewModel() {
|
|||||||
val entryHistory : LiveData<List<EntryInfo>> get() = _entryHistory
|
val entryHistory : LiveData<List<EntryInfo>> get() = _entryHistory
|
||||||
private val _entryHistory = MutableLiveData<List<EntryInfo>>()
|
private val _entryHistory = MutableLiveData<List<EntryInfo>>()
|
||||||
|
|
||||||
val onOtpElementUpdated : LiveData<OtpElement> get() = _onOtpElementUpdated
|
val onOtpElementUpdated : LiveData<OtpElement?> get() = _onOtpElementUpdated
|
||||||
private val _onOtpElementUpdated = SingleLiveEvent<OtpElement>()
|
private val _onOtpElementUpdated = SingleLiveEvent<OtpElement?>()
|
||||||
|
|
||||||
val attachmentSelected : LiveData<Attachment> get() = _attachmentSelected
|
val attachmentSelected : LiveData<Attachment> get() = _attachmentSelected
|
||||||
private val _attachmentSelected = SingleLiveEvent<Attachment>()
|
private val _attachmentSelected = SingleLiveEvent<Attachment>()
|
||||||
@@ -122,7 +122,7 @@ class EntryViewModel: ViewModel() {
|
|||||||
return entryIsHistory.value ?: false
|
return entryIsHistory.value ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onOtpElementUpdated(optElement: OtpElement) {
|
fun onOtpElementUpdated(optElement: OtpElement?) {
|
||||||
_onOtpElementUpdated.value = optElement
|
_onOtpElementUpdated.value = optElement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user