mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Global OTP variables, add progress bar, remove seconds
This commit is contained in:
@@ -32,6 +32,7 @@ import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.Toast
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
|
||||
@@ -59,6 +60,7 @@ class EntryActivity : LockingHideActivity() {
|
||||
private var titleIconView: ImageView? = null
|
||||
private var historyView: View? = null
|
||||
private var entryContentsView: EntryContentsView? = null
|
||||
private var entryProgress: ProgressBar? = null
|
||||
private var toolbar: Toolbar? = null
|
||||
|
||||
private var mDatabase: Database? = null
|
||||
@@ -103,6 +105,7 @@ class EntryActivity : LockingHideActivity() {
|
||||
historyView = findViewById(R.id.history_container)
|
||||
entryContentsView = findViewById(R.id.entry_contents)
|
||||
entryContentsView?.applyFontVisibilityToFields(PreferencesUtil.fieldFontIsInVisibility(this))
|
||||
entryProgress = findViewById(R.id.entry_progress)
|
||||
|
||||
// Init the clipboard helper
|
||||
clipboardHelper = ClipboardHelper(this)
|
||||
@@ -226,10 +229,11 @@ class EntryActivity : LockingHideActivity() {
|
||||
}
|
||||
|
||||
mOtpEntryFields?.let { otpEntryFields ->
|
||||
entryContentsView?.assignTotp(otpEntryFields, View.OnClickListener {
|
||||
entryContentsView?.assignOtp(otpEntryFields, entryProgress,
|
||||
View.OnClickListener {
|
||||
clipboardHelper?.timeoutCopyToClipboard(
|
||||
otpEntryFields.token,
|
||||
getString(R.string.copy_field, getString(R.string.entry_totp))
|
||||
getString(R.string.copy_field, getString(R.string.entry_otp))
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -120,8 +120,8 @@ public class OtpEntryFields {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isConfigured() {
|
||||
return type != OtpType.UNDEFINED;
|
||||
public OtpType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
@@ -174,6 +174,10 @@ public class OtpEntryFields {
|
||||
}
|
||||
}
|
||||
|
||||
public int getStep() {
|
||||
return step;
|
||||
}
|
||||
|
||||
private void setStep(int step) {
|
||||
if (step <= 0 || step > 60) {
|
||||
this.step = DEFAULT_STEP;
|
||||
|
||||
@@ -20,7 +20,6 @@ package com.kunzisoft.keepass.view
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.os.Handler
|
||||
import android.text.method.PasswordTransformationMethod
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
@@ -28,6 +27,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
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
|
||||
@@ -37,8 +37,8 @@ import com.kunzisoft.keepass.adapters.EntryHistoryAdapter
|
||||
import com.kunzisoft.keepass.database.element.EntryVersioned
|
||||
import com.kunzisoft.keepass.database.element.PwDate
|
||||
import com.kunzisoft.keepass.database.element.security.ProtectedString
|
||||
import java.util.*
|
||||
import com.kunzisoft.keepass.otp.OtpEntryFields
|
||||
import java.util.*
|
||||
|
||||
class EntryContentsView @JvmOverloads constructor(context: Context,
|
||||
var attrs: AttributeSet? = null,
|
||||
@@ -56,10 +56,10 @@ class EntryContentsView @JvmOverloads constructor(context: Context,
|
||||
private val passwordView: TextView
|
||||
private val passwordActionView: ImageView
|
||||
|
||||
private val totpContainerView: View
|
||||
private val totpView: TextView
|
||||
private val totpActionView: ImageView
|
||||
private var totpCurrentToken: String = ""
|
||||
private val otpContainerView: View
|
||||
private val otpLabelView: TextView
|
||||
private val otpView: TextView
|
||||
private val otpActionView: ImageView
|
||||
|
||||
private val urlContainerView: View
|
||||
private val urlView: TextView
|
||||
@@ -100,9 +100,10 @@ class EntryContentsView @JvmOverloads constructor(context: Context,
|
||||
passwordView = findViewById(R.id.entry_password)
|
||||
passwordActionView = findViewById(R.id.entry_password_action_image)
|
||||
|
||||
totpContainerView = findViewById(R.id.entry_totp_container);
|
||||
totpView = findViewById(R.id.entry_totp);
|
||||
totpActionView = findViewById(R.id.entry_totp_action_image);
|
||||
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)
|
||||
|
||||
urlContainerView = findViewById(R.id.entry_url_container)
|
||||
urlView = findViewById(R.id.entry_url)
|
||||
@@ -210,36 +211,50 @@ class EntryContentsView @JvmOverloads constructor(context: Context,
|
||||
}
|
||||
}
|
||||
|
||||
fun assignTotp(otpEntryFields: OtpEntryFields, onClickListener: OnClickListener) {
|
||||
if (otpEntryFields.isConfigured) {
|
||||
totpContainerView.visibility = View.VISIBLE
|
||||
fun assignOtp(otpEntryFields: OtpEntryFields,
|
||||
otpProgressView: ProgressBar?,
|
||||
onClickListener: OnClickListener) {
|
||||
if (otpEntryFields.type != OtpEntryFields.OtpType.UNDEFINED) {
|
||||
otpContainerView.visibility = View.VISIBLE
|
||||
|
||||
val totpToken = otpEntryFields.token
|
||||
if (totpToken.isEmpty()) {
|
||||
totpView.text = context.getString(R.string.error_invalid_TOTP)
|
||||
totpActionView
|
||||
.setColorFilter(ContextCompat.getColor(context, R.color.grey_dark))
|
||||
assignTotpCopyListener(null)
|
||||
if (otpEntryFields.token.isEmpty()) {
|
||||
otpView.text = context.getString(R.string.error_invalid_OTP)
|
||||
otpActionView.setColorFilter(ContextCompat.getColor(context, R.color.grey_dark))
|
||||
assignOtpCopyListener(null)
|
||||
} else {
|
||||
assignTotpCopyListener(onClickListener)
|
||||
totpCurrentToken = otpEntryFields.token
|
||||
val totpHandler = Handler()
|
||||
totpHandler.post(object : Runnable {
|
||||
override fun run() {
|
||||
if (otpEntryFields.shouldRefreshToken()) {
|
||||
totpCurrentToken = otpEntryFields.token
|
||||
}
|
||||
totpView.text = context.getString(R.string.entry_totp_format,
|
||||
totpCurrentToken, otpEntryFields.secondsRemaining)
|
||||
totpHandler.postDelayed(this, 1000)
|
||||
assignOtpCopyListener(onClickListener)
|
||||
otpView.text = otpEntryFields.token
|
||||
otpLabelView.text = otpEntryFields.type.name
|
||||
|
||||
when (otpEntryFields.type) {
|
||||
// Only add token if HOTP
|
||||
OtpEntryFields.OtpType.HOTP -> {
|
||||
}
|
||||
})
|
||||
// Refresh view if TOTP
|
||||
OtpEntryFields.OtpType.TOTP -> {
|
||||
otpProgressView?.apply {
|
||||
max = otpEntryFields.step
|
||||
progress = otpEntryFields.secondsRemaining
|
||||
visibility = View.VISIBLE
|
||||
}
|
||||
otpContainerView.post(object : Runnable {
|
||||
override fun run() {
|
||||
if (otpEntryFields.shouldRefreshToken()) {
|
||||
otpView.text = otpEntryFields.token
|
||||
}
|
||||
otpProgressView?.progress = otpEntryFields.secondsRemaining
|
||||
otpContainerView.postDelayed(this, 1000)
|
||||
}
|
||||
})
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun assignTotpCopyListener(onClickListener: OnClickListener?) {
|
||||
totpActionView.setOnClickListener(onClickListener)
|
||||
fun assignOtpCopyListener(onClickListener: OnClickListener?) {
|
||||
otpActionView.setOnClickListener(onClickListener)
|
||||
}
|
||||
|
||||
fun assignURL(url: String?) {
|
||||
|
||||
@@ -72,6 +72,17 @@
|
||||
tools:targetApi="lollipop">
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
<ProgressBar
|
||||
android:visibility="gone"
|
||||
android:id="@+id/entry_progress"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:indeterminate="false"
|
||||
android:progress="10"
|
||||
android:max="30"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="4dp" />
|
||||
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
|
||||
@@ -105,34 +105,34 @@
|
||||
android:tint="?attr/colorAccent" />
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- TOTP -->
|
||||
<!-- OTP -->
|
||||
<RelativeLayout
|
||||
android:id="@+id/entry_totp_container"
|
||||
android:id="@+id/entry_otp_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone">
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/entry_totp_label"
|
||||
android:id="@+id/entry_otp_label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/entry_totp"
|
||||
android:text="@string/entry_otp"
|
||||
style="@style/KeepassDXStyle.TextAppearance.LabelTextStyle" />
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/entry_totp"
|
||||
android:id="@+id/entry_otp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/entry_totp_label"
|
||||
android:layout_toLeftOf="@+id/entry_totp_action_image"
|
||||
android:layout_toStartOf="@+id/entry_totp_action_image"
|
||||
android:layout_below="@+id/entry_otp_label"
|
||||
android:layout_toLeftOf="@+id/entry_otp_action_image"
|
||||
android:layout_toStartOf="@+id/entry_otp_action_image"
|
||||
android:textIsSelectable="true"
|
||||
style="@style/KeepassDXStyle.TextAppearance.TextEntryItem" />
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/entry_totp_action_image"
|
||||
android:id="@+id/entry_otp_action_image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@+id/entry_totp_label"
|
||||
android:layout_below="@+id/entry_otp_label"
|
||||
android:src="@drawable/ic_content_copy_white_24dp"
|
||||
android:tint="?attr/colorAccent" />
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -87,8 +87,7 @@
|
||||
<string name="entry_password">Password</string>
|
||||
<string name="entry_save">Save</string>
|
||||
<string name="entry_title">Title</string>
|
||||
<string name="entry_totp">TOTP</string>
|
||||
<string name="entry_totp_format">%1$s (%2$d)</string>
|
||||
<string name="entry_otp">OTP</string>
|
||||
<string name="entry_url">URL</string>
|
||||
<string name="entry_user_name">Username</string>
|
||||
<string name="error_arc4">The ARCFOUR stream cipher is not supported.</string>
|
||||
@@ -96,7 +95,7 @@
|
||||
<string name="error_file_not_create">Could not create file:</string>
|
||||
<string name="error_invalid_db">Could not read database.</string>
|
||||
<string name="error_invalid_path">Make sure the path is correct.</string>
|
||||
<string name="error_invalid_TOTP">Invalid TOTP secret.</string>
|
||||
<string name="error_invalid_OTP">Invalid OTP secret.</string>
|
||||
<string name="error_no_name">Enter a name.</string>
|
||||
<string name="error_nokeyfile">Select a keyfile.</string>
|
||||
<string name="error_out_of_memory">No memory to load your entire database.</string>
|
||||
|
||||
Reference in New Issue
Block a user