Global OTP variables, add progress bar, remove seconds

This commit is contained in:
J-Jamet
2019-11-05 16:04:30 +01:00
parent f122c2832c
commit 16320abb7d
6 changed files with 82 additions and 49 deletions

View File

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

View File

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

View File

@@ -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?) {

View File

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

View File

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

View File

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