mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Fix fist time clipboard warning and better views implementation
This commit is contained in:
@@ -45,7 +45,6 @@ import com.kunzisoft.keepass.icons.assignDatabaseIcon
|
||||
import com.kunzisoft.keepass.magikeyboard.MagikIME
|
||||
import com.kunzisoft.keepass.notifications.ClipboardEntryNotificationService
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil.isFirstTimeAskAllowCopyPasswordAndProtectedFields
|
||||
import com.kunzisoft.keepass.settings.SettingsAutofillActivity
|
||||
import com.kunzisoft.keepass.timeout.ClipboardHelper
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
@@ -164,9 +163,33 @@ class EntryActivity : LockingHideActivity() {
|
||||
getString(R.string.entry_user_name)))
|
||||
})
|
||||
|
||||
val allowCopyPassword = PreferencesUtil.allowCopyPasswordAndProtectedFields(this)
|
||||
entryContentsView?.assignPassword(entry.password, allowCopyPassword)
|
||||
if (allowCopyPassword) {
|
||||
val isFirstTimeAskAllowCopyPasswordAndProtectedFields =
|
||||
PreferencesUtil.isFirstTimeAskAllowCopyPasswordAndProtectedFields(this)
|
||||
val allowCopyPasswordAndProtectedFields =
|
||||
PreferencesUtil.allowCopyPasswordAndProtectedFields(this)
|
||||
|
||||
val showWarningClipboardDialogOnClickListener = View.OnClickListener {
|
||||
AlertDialog.Builder(this@EntryActivity)
|
||||
.setMessage(getString(R.string.allow_copy_password_warning) +
|
||||
"\n\n" +
|
||||
getString(R.string.clipboard_warning))
|
||||
.create().apply {
|
||||
setButton(AlertDialog.BUTTON_POSITIVE, getText(R.string.enable)) {dialog, _ ->
|
||||
PreferencesUtil.setAllowCopyPasswordAndProtectedFields(this@EntryActivity, true)
|
||||
dialog.dismiss()
|
||||
fillEntryDataInContentsView(entry)
|
||||
}
|
||||
setButton(AlertDialog.BUTTON_NEGATIVE, getText(R.string.disable)) { dialog, _ ->
|
||||
PreferencesUtil.setAllowCopyPasswordAndProtectedFields(this@EntryActivity, false)
|
||||
dialog.dismiss()
|
||||
fillEntryDataInContentsView(entry)
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
entryContentsView?.assignPassword(entry.password, allowCopyPasswordAndProtectedFields)
|
||||
if (allowCopyPasswordAndProtectedFields) {
|
||||
entryContentsView?.assignPasswordCopyListener(View.OnClickListener {
|
||||
clipboardHelper?.timeoutCopyToClipboard(entry.password,
|
||||
getString(R.string.copy_field,
|
||||
@@ -174,27 +197,8 @@ class EntryActivity : LockingHideActivity() {
|
||||
})
|
||||
} else {
|
||||
// If dialog not already shown
|
||||
if (isFirstTimeAskAllowCopyPasswordAndProtectedFields(this)) {
|
||||
entryContentsView?.assignPasswordCopyListener(View.OnClickListener {
|
||||
val message = getString(R.string.allow_copy_password_warning) +
|
||||
"\n\n" +
|
||||
getString(R.string.clipboard_warning)
|
||||
val warningDialog = AlertDialog.Builder(this@EntryActivity)
|
||||
.setMessage(message).create()
|
||||
warningDialog.setButton(AlertDialog.BUTTON_POSITIVE, getText(android.R.string.ok)
|
||||
) { dialog, _ ->
|
||||
PreferencesUtil.setAllowCopyPasswordAndProtectedFields(this@EntryActivity, true)
|
||||
dialog.dismiss()
|
||||
fillEntryDataInContentsView(entry)
|
||||
}
|
||||
warningDialog.setButton(AlertDialog.BUTTON_NEGATIVE, getText(android.R.string.cancel)
|
||||
) { dialog, _ ->
|
||||
PreferencesUtil.setAllowCopyPasswordAndProtectedFields(this@EntryActivity, false)
|
||||
dialog.dismiss()
|
||||
fillEntryDataInContentsView(entry)
|
||||
}
|
||||
warningDialog.show()
|
||||
})
|
||||
if (isFirstTimeAskAllowCopyPasswordAndProtectedFields) {
|
||||
entryContentsView?.assignPasswordCopyListener(showWarningClipboardDialogOnClickListener)
|
||||
} else {
|
||||
entryContentsView?.assignPasswordCopyListener(null)
|
||||
}
|
||||
@@ -209,13 +213,23 @@ class EntryActivity : LockingHideActivity() {
|
||||
entryContentsView?.clearExtraFields()
|
||||
|
||||
entry.fields.doActionToAllCustomProtectedField { label, value ->
|
||||
val showAction = !value.isProtected || PreferencesUtil.allowCopyPasswordAndProtectedFields(this@EntryActivity)
|
||||
entryContentsView?.addExtraField(label, value, showAction, View.OnClickListener {
|
||||
clipboardHelper?.timeoutCopyToClipboard(
|
||||
value.toString(),
|
||||
getString(R.string.copy_field, label)
|
||||
)
|
||||
})
|
||||
|
||||
val allowCopyProtectedField = !value.isProtected || allowCopyPasswordAndProtectedFields
|
||||
if (allowCopyProtectedField) {
|
||||
entryContentsView?.addExtraField(label, value, allowCopyProtectedField, View.OnClickListener {
|
||||
clipboardHelper?.timeoutCopyToClipboard(
|
||||
value.toString(),
|
||||
getString(R.string.copy_field, label)
|
||||
)
|
||||
})
|
||||
} else {
|
||||
// If dialog not already shown
|
||||
if (isFirstTimeAskAllowCopyPasswordAndProtectedFields) {
|
||||
entryContentsView?.addExtraField(label, value, allowCopyProtectedField, showWarningClipboardDialogOnClickListener)
|
||||
} else {
|
||||
entryContentsView?.addExtraField(label, value, allowCopyProtectedField, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -401,11 +401,11 @@ class NestedSettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferen
|
||||
.setMessage(message)
|
||||
.create()
|
||||
.apply {
|
||||
setButton(AlertDialog.BUTTON_POSITIVE, getText(android.R.string.ok))
|
||||
setButton(AlertDialog.BUTTON_POSITIVE, getText(R.string.enable))
|
||||
{ dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
setButton(AlertDialog.BUTTON_NEGATIVE, getText(android.R.string.cancel))
|
||||
setButton(AlertDialog.BUTTON_NEGATIVE, getText(R.string.disable))
|
||||
{ dialog, _ ->
|
||||
copyPasswordPreference.isChecked = false
|
||||
dialog.dismiss()
|
||||
|
||||
@@ -36,8 +36,10 @@ import android.widget.RelativeLayout
|
||||
|
||||
import com.kunzisoft.keepass.R
|
||||
|
||||
class AddNodeButtonView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
|
||||
: RelativeLayout(context, attrs) {
|
||||
class AddNodeButtonView @JvmOverloads constructor(context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyle: Int = 0)
|
||||
: RelativeLayout(context, attrs, defStyle) {
|
||||
|
||||
var addButtonView: FloatingActionButton? = null
|
||||
private var addEntryView: View? = null
|
||||
|
||||
@@ -35,7 +35,10 @@ import com.kunzisoft.keepass.utils.applyFontVisibility
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
|
||||
class EntryContentsView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) {
|
||||
class EntryContentsView @JvmOverloads constructor(context: Context,
|
||||
var attrs: AttributeSet? = null,
|
||||
var defStyle: Int = 0)
|
||||
: LinearLayout(context, attrs, defStyle) {
|
||||
|
||||
private var fontInVisibility: Boolean = false
|
||||
private val colorAccent: Int
|
||||
@@ -136,10 +139,10 @@ class EntryContentsView @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
if (fontInVisibility)
|
||||
applyFontVisibility()
|
||||
}
|
||||
if (!allowCopyPassword) {
|
||||
passwordActionView.setColorFilter(ContextCompat.getColor(context, R.color.grey_dark))
|
||||
} else {
|
||||
if (allowCopyPassword) {
|
||||
passwordActionView.setColorFilter(colorAccent)
|
||||
} else {
|
||||
passwordActionView.setColorFilter(ContextCompat.getColor(context, R.color.grey_dark))
|
||||
}
|
||||
} else {
|
||||
passwordContainerView.visibility = View.GONE
|
||||
@@ -147,9 +150,12 @@ class EntryContentsView @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
}
|
||||
|
||||
fun assignPasswordCopyListener(onClickListener: OnClickListener?) {
|
||||
if (onClickListener == null)
|
||||
isClickable = false
|
||||
passwordActionView.setOnClickListener(onClickListener)
|
||||
passwordActionView.apply {
|
||||
setOnClickListener(onClickListener)
|
||||
if (onClickListener == null) {
|
||||
visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun atLeastOneFieldProtectedPresent(): Boolean {
|
||||
@@ -202,13 +208,23 @@ class EntryContentsView @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
}
|
||||
}
|
||||
|
||||
fun addExtraField(title: String, value: ProtectedString, showAction: Boolean, onActionClickListener: OnClickListener) {
|
||||
val entryCustomField: EntryCustomField
|
||||
if (value.isProtected)
|
||||
entryCustomField = EntryCustomFieldProtected(context, null, title, value, showAction, onActionClickListener)
|
||||
else
|
||||
entryCustomField = EntryCustomField(context, null, title, value, showAction, onActionClickListener)
|
||||
entryCustomField.applyFontVisibility(fontInVisibility)
|
||||
fun addExtraField(title: String,
|
||||
value: ProtectedString,
|
||||
enableActionButton: Boolean,
|
||||
onActionClickListener: OnClickListener?) {
|
||||
|
||||
val entryCustomField: EntryCustomField =
|
||||
if (value.isProtected)
|
||||
EntryCustomFieldProtected(context, attrs, defStyle)
|
||||
else
|
||||
EntryCustomField(context, attrs, defStyle)
|
||||
entryCustomField.apply {
|
||||
assignLabel(title)
|
||||
assignValue(value.toString())
|
||||
enableActionButton(enableActionButton)
|
||||
assignActionButtonClickListener(onActionClickListener)
|
||||
applyFontVisibility(fontInVisibility)
|
||||
}
|
||||
extrasView.addView(entryCustomField)
|
||||
extrasContainerView.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
package com.kunzisoft.keepass.view
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
@@ -27,24 +28,18 @@ import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.database.element.security.ProtectedString
|
||||
import com.kunzisoft.keepass.utils.applyFontVisibility
|
||||
|
||||
open class EntryCustomField(context: Context,
|
||||
attrs: AttributeSet?,
|
||||
label: String?,
|
||||
value: ProtectedString?,
|
||||
showAction: Boolean,
|
||||
onClickActionListener: OnClickListener?)
|
||||
: LinearLayout(context, attrs) {
|
||||
open class EntryCustomField @JvmOverloads constructor(context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyle: Int = 0)
|
||||
: LinearLayout(context, attrs, defStyle) {
|
||||
|
||||
protected val labelView: TextView
|
||||
private val labelView: TextView
|
||||
protected val valueView: TextView
|
||||
protected val actionImageView: ImageView
|
||||
private val actionImageView: ImageView
|
||||
|
||||
@JvmOverloads
|
||||
constructor(context: Context, attrs: AttributeSet? = null, title: String? = null, value: ProtectedString? = null)
|
||||
: this(context, attrs, title, value, false, null)
|
||||
private val colorAccent: Int
|
||||
|
||||
init {
|
||||
|
||||
@@ -55,16 +50,10 @@ open class EntryCustomField(context: Context,
|
||||
valueView = findViewById(R.id.value)
|
||||
actionImageView = findViewById(R.id.action_image)
|
||||
|
||||
setLabel(label)
|
||||
setValue(value)
|
||||
|
||||
if (showAction) {
|
||||
actionImageView.isEnabled = true
|
||||
setAction(onClickActionListener)
|
||||
} else {
|
||||
actionImageView.isEnabled = false
|
||||
actionImageView.setColorFilter(ContextCompat.getColor(getContext(), R.color.grey_dark))
|
||||
}
|
||||
val attrColorAccent = intArrayOf(R.attr.colorAccent)
|
||||
val taColorAccent = context.theme.obtainStyledAttributes(attrColorAccent)
|
||||
colorAccent = taColorAccent.getColor(0, Color.BLACK)
|
||||
taColorAccent.recycle()
|
||||
}
|
||||
|
||||
fun applyFontVisibility(fontInVisibility: Boolean) {
|
||||
@@ -72,23 +61,24 @@ open class EntryCustomField(context: Context,
|
||||
valueView.applyFontVisibility()
|
||||
}
|
||||
|
||||
fun setLabel(label: String?) {
|
||||
if (label != null) {
|
||||
labelView.text = label
|
||||
}
|
||||
fun assignLabel(label: String?) {
|
||||
labelView.text = label ?: ""
|
||||
}
|
||||
|
||||
open fun setValue(value: ProtectedString?) {
|
||||
if (value != null) {
|
||||
valueView.text = value.toString()
|
||||
}
|
||||
fun assignValue(value: String?) {
|
||||
valueView.text = value ?: ""
|
||||
}
|
||||
|
||||
fun setAction(onClickListener: OnClickListener?) {
|
||||
if (onClickListener != null) {
|
||||
actionImageView.setOnClickListener(onClickListener)
|
||||
fun enableActionButton(enable: Boolean) {
|
||||
if (enable) {
|
||||
actionImageView.setColorFilter(colorAccent)
|
||||
} else {
|
||||
actionImageView.visibility = GONE
|
||||
actionImageView.setColorFilter(ContextCompat.getColor(context, R.color.grey_dark))
|
||||
}
|
||||
}
|
||||
|
||||
fun assignActionButtonClickListener(onClickActionListener: OnClickListener?) {
|
||||
actionImageView.setOnClickListener(onClickActionListener)
|
||||
actionImageView.visibility = if (onClickActionListener == null) GONE else VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,22 +23,15 @@ import android.content.Context
|
||||
import android.text.method.PasswordTransformationMethod
|
||||
import android.util.AttributeSet
|
||||
|
||||
import com.kunzisoft.keepass.database.element.security.ProtectedString
|
||||
class EntryCustomFieldProtected @JvmOverloads constructor(context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyle: Int = 0)
|
||||
: EntryCustomField(context, attrs, defStyle) {
|
||||
|
||||
class EntryCustomFieldProtected : EntryCustomField {
|
||||
|
||||
constructor(context: Context) : super(context)
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet?, label: String?, value: ProtectedString?) : super(context, attrs, label, value)
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet?, label: String?, value: ProtectedString?, showAction: Boolean, onClickActionListener: OnClickListener?) : super(context, attrs, label, value, showAction, onClickActionListener)
|
||||
|
||||
override fun setValue(value: ProtectedString?) {
|
||||
fun setValue(value: String?, isProtected: Boolean) {
|
||||
if (value != null) {
|
||||
valueView.text = value.toString()
|
||||
setHiddenPasswordStyle(value.isProtected)
|
||||
valueView.text = value
|
||||
setHiddenPasswordStyle(isProtected)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,10 @@ import com.kunzisoft.keepass.icons.assignDefaultDatabaseIcon
|
||||
import com.kunzisoft.keepass.model.Field
|
||||
import com.kunzisoft.keepass.utils.applyFontVisibility
|
||||
|
||||
class EntryEditContentsView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) {
|
||||
class EntryEditContentsView @JvmOverloads constructor(context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyle: Int = 0)
|
||||
: LinearLayout(context, attrs, defStyle) {
|
||||
|
||||
private var fontInVisibility: Boolean = false
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import com.kunzisoft.keepass.fingerprint.FingerPrintAnimatedVector
|
||||
class FingerPrintInfoView @JvmOverloads constructor(context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyle: Int = 0)
|
||||
: LinearLayout(context, attrs) {
|
||||
: LinearLayout(context, attrs, defStyle) {
|
||||
|
||||
private val fingerPrintContainerView: View
|
||||
private var fingerPrintAnimatedVector: FingerPrintAnimatedVector? = null
|
||||
|
||||
@@ -284,6 +284,8 @@
|
||||
<string name="allow_copy_password_title">Clipboard trust</string>
|
||||
<string name="allow_copy_password_summary">Allow the entry password and protected fields to enter the clipboard</string>
|
||||
<string name="allow_copy_password_warning">WARNING: The clipboard is shared by all apps. If sensitive data is copied, other software may recover it.</string>
|
||||
<string name="enable">Enable</string>
|
||||
<string name="disable">Disable</string>
|
||||
<string name="clear_clipboard_notification_title">Clear at closing</string>
|
||||
<string name="clear_clipboard_notification_summary">Close the database when closing the notification</string>
|
||||
<string name="open_link_database">Link of database file to open</string>
|
||||
|
||||
Reference in New Issue
Block a user