Compare commits

...

14 Commits
3.0.0 ... 3.0.1

Author SHA1 Message Date
J-Jamet
b4f2a1eb89 Merge branch 'release/3.0.1' 2021-09-15 13:24:53 +02:00
J-Jamet
e9fc9cbc2a Capture cast exception 2021-09-15 12:21:44 +02:00
J-Jamet
b809180a1b Small changes 2021-09-15 11:25:15 +02:00
J-Jamet
ecc75df3a1 Fix search actions #1091 #1092 2021-09-15 11:16:32 +02:00
J-Jamet
d1b6863143 Update CHANGELOG 2021-09-15 10:36:41 +02:00
J-Jamet
faf27143aa Fix timeout reset #1107 2021-09-15 10:33:37 +02:00
J-Jamet
aee58a4475 Fix exception after group name change and save #1112 2021-09-15 09:48:48 +02:00
J-Jamet
c5e07f643f Fix Magikeyboard URL auto action #1100 2021-09-14 20:40:22 +02:00
J-Jamet
818f5820d5 Update CHANGELOG 2021-09-14 20:13:35 +02:00
J-Jamet
77c6e28876 Fix max lines #1073 2021-09-14 20:06:49 +02:00
J-Jamet
fb7f66012d Upgrade to 3.0.1 2021-09-14 19:35:30 +02:00
J-Jamet
0f7f7bbe6c Min height to 48dp 2021-09-14 19:30:50 +02:00
J-Jamet
8dedb8deb4 Fix text dimension 2021-09-14 19:10:48 +02:00
J-Jamet
d284db4d3c Merge tag '3.0.0' into develop
3.0.0
2021-09-07 18:43:40 +02:00
14 changed files with 118 additions and 73 deletions

View File

@@ -1,3 +1,12 @@
KeePassDX(3.0.1)
* Fix text size and smallest margin #1085
* Fix number of lines during an edition #1073
* Fix Magikeyboard URL auto action #1100
* Fix exception after group name change and save #1112
* Fix timeout reset #1107
* Fix search actions #1091 #1092
* Small changes #1106 #1085
KeePassDX(3.0.0) KeePassDX(3.0.0)
* Add / Manage dynamic templates #191 * Add / Manage dynamic templates #191
* Manually select RecycleBin group and Templates group #191 * Manually select RecycleBin group and Templates group #191

View File

@@ -11,8 +11,8 @@ android {
applicationId "com.kunzisoft.keepass" applicationId "com.kunzisoft.keepass"
minSdkVersion 15 minSdkVersion 15
targetSdkVersion 30 targetSdkVersion 30
versionCode = 87 versionCode = 88
versionName = "3.0.0" versionName = "3.0.1"
multiDexEnabled true multiDexEnabled true
testApplicationId = "com.kunzisoft.keepass.tests" testApplicationId = "com.kunzisoft.keepass.tests"

View File

@@ -653,6 +653,8 @@ class GroupActivity : DatabaseLockActivity(),
Log.e(TAG, "Node can't be cast in Entry") Log.e(TAG, "Node can't be cast in Entry")
} }
} }
reloadGroupIfSearch()
} }
private fun entrySelectedForSave(database: Database, entry: Entry, searchInfo: SearchInfo) { private fun entrySelectedForSave(database: Database, entry: Entry, searchInfo: SearchInfo) {
@@ -738,6 +740,12 @@ class GroupActivity : DatabaseLockActivity(),
actionNodeMode?.finish() actionNodeMode?.finish()
} }
private fun reloadGroupIfSearch() {
if (Intent.ACTION_SEARCH == intent.action) {
reloadCurrentGroup()
}
}
override fun onNodeSelected( override fun onNodeSelected(
database: Database, database: Database,
nodes: List<Node> nodes: List<Node>
@@ -793,6 +801,7 @@ class GroupActivity : DatabaseLockActivity(),
(node as Entry).nodeId (node as Entry).nodeId
) )
} }
reloadGroupIfSearch()
return true return true
} }
@@ -847,6 +856,7 @@ class GroupActivity : DatabaseLockActivity(),
): Boolean { ): Boolean {
deleteNodes(nodes) deleteNodes(nodes)
finishNodeAction() finishNodeAction()
reloadGroupIfSearch()
return true return true
} }
@@ -1093,7 +1103,7 @@ class GroupActivity : DatabaseLockActivity(),
try { try {
mGroupViewModel.loadGroup(mDatabase, mCurrentGroupState) mGroupViewModel.loadGroup(mDatabase, mCurrentGroupState)
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Unable to rebuild the list after deletion", e) Log.e(TAG, "Unable to rebuild the group", e)
} }
} }

View File

@@ -67,8 +67,10 @@ class NodeAdapter (private val context: Context,
private var mCalculateViewTypeTextSize = Array(2) { true } // number of view type private var mCalculateViewTypeTextSize = Array(2) { true } // number of view type
private var mTextSizeUnit: Int = TypedValue.COMPLEX_UNIT_PX private var mTextSizeUnit: Int = TypedValue.COMPLEX_UNIT_PX
private var mPrefSizeMultiplier: Float = 0F private var mPrefSizeMultiplier: Float = 0F
private var mSubtextDefaultDimension: Float = 0F private var mTextDefaultDimension: Float = 0F
private var mInfoTextDefaultDimension: Float = 0F private var mSubTextDefaultDimension: Float = 0F
private var mMetaTextDefaultDimension: Float = 0F
private var mOtpTokenTextDefaultDimension: Float = 0F
private var mNumberChildrenTextDefaultDimension: Float = 0F private var mNumberChildrenTextDefaultDimension: Float = 0F
private var mIconDefaultDimension: Float = 0F private var mIconDefaultDimension: Float = 0F
@@ -303,8 +305,10 @@ class NodeAdapter (private val context: Context,
mInflater.inflate(R.layout.item_list_nodes_entry, parent, false) mInflater.inflate(R.layout.item_list_nodes_entry, parent, false)
} }
val nodeViewHolder = NodeViewHolder(view) val nodeViewHolder = NodeViewHolder(view)
mInfoTextDefaultDimension = nodeViewHolder.text.textSize mTextDefaultDimension = nodeViewHolder.text.textSize
mSubtextDefaultDimension = nodeViewHolder.subText.textSize mSubTextDefaultDimension = nodeViewHolder.subText?.textSize ?: mSubTextDefaultDimension
mMetaTextDefaultDimension = nodeViewHolder.meta.textSize
mOtpTokenTextDefaultDimension = nodeViewHolder.otpToken?.textSize ?: mOtpTokenTextDefaultDimension
nodeViewHolder.numberChildren?.let { nodeViewHolder.numberChildren?.let {
mNumberChildrenTextDefaultDimension = it.textSize mNumberChildrenTextDefaultDimension = it.textSize
} }
@@ -315,7 +319,9 @@ class NodeAdapter (private val context: Context,
val subNode = mNodeSortedList.get(position) val subNode = mNodeSortedList.get(position)
// Node selection // Node selection
holder.container.isSelected = mActionNodesList.contains(subNode) holder.container.apply {
isSelected = mActionNodesList.contains(subNode)
}
// Assign image // Assign image
val iconColor = if (holder.container.isSelected) val iconColor = if (holder.container.isSelected)
@@ -337,19 +343,18 @@ class NodeAdapter (private val context: Context,
// Assign text // Assign text
holder.text.apply { holder.text.apply {
text = subNode.title text = subNode.title
setTextSize(mTextSizeUnit, mInfoTextDefaultDimension, mPrefSizeMultiplier) setTextSize(mTextSizeUnit, mTextDefaultDimension, mPrefSizeMultiplier)
strikeOut(subNode.isCurrentlyExpires) strikeOut(subNode.isCurrentlyExpires)
} }
// Add subText with username
holder.subText.apply {
text = ""
strikeOut(subNode.isCurrentlyExpires)
visibility = View.GONE
}
// Add meta text to show UUID // Add meta text to show UUID
holder.meta.apply { holder.meta.apply {
text = subNode.nodeId.toString() if (mShowUUID) {
visibility = if (mShowUUID) View.VISIBLE else View.GONE text = subNode.nodeId.toString()
setTextSize(mTextSizeUnit, mMetaTextDefaultDimension, mPrefSizeMultiplier)
visibility = View.VISIBLE
} else {
visibility = View.GONE
}
} }
// Specific elements for entry // Specific elements for entry
@@ -358,12 +363,16 @@ class NodeAdapter (private val context: Context,
database.startManageEntry(entry) database.startManageEntry(entry)
holder.text.text = entry.getVisualTitle() holder.text.text = entry.getVisualTitle()
holder.subText.apply { // Add subText with username
holder.subText?.apply {
val username = entry.username val username = entry.username
if (mShowUserNames && username.isNotEmpty()) { if (mShowUserNames && username.isNotEmpty()) {
visibility = View.VISIBLE visibility = View.VISIBLE
text = username text = username
setTextSize(mTextSizeUnit, mSubtextDefaultDimension, mPrefSizeMultiplier) setTextSize(mTextSizeUnit, mSubTextDefaultDimension, mPrefSizeMultiplier)
strikeOut(subNode.isCurrentlyExpires)
} else {
visibility = View.GONE
} }
} }
@@ -431,7 +440,10 @@ class NodeAdapter (private val context: Context,
} }
} }
} }
holder?.otpToken?.text = otpElement?.token holder?.otpToken?.apply {
text = otpElement?.token
setTextSize(mTextSizeUnit, mOtpTokenTextDefaultDimension, mPrefSizeMultiplier)
}
holder?.otpContainer?.setOnClickListener { holder?.otpContainer?.setOnClickListener {
otpElement?.token?.let { token -> otpElement?.token?.let { token ->
Toast.makeText( Toast.makeText(
@@ -483,7 +495,7 @@ class NodeAdapter (private val context: Context,
var imageIdentifier: ImageView? = itemView.findViewById(R.id.node_image_identifier) var imageIdentifier: ImageView? = itemView.findViewById(R.id.node_image_identifier)
var icon: ImageView = itemView.findViewById(R.id.node_icon) var icon: ImageView = itemView.findViewById(R.id.node_icon)
var text: TextView = itemView.findViewById(R.id.node_text) var text: TextView = itemView.findViewById(R.id.node_text)
var subText: TextView = itemView.findViewById(R.id.node_subtext) var subText: TextView? = itemView.findViewById(R.id.node_subtext)
var meta: TextView = itemView.findViewById(R.id.node_meta) var meta: TextView = itemView.findViewById(R.id.node_meta)
var otpContainer: ViewGroup? = itemView.findViewById(R.id.node_otp_container) var otpContainer: ViewGroup? = itemView.findViewById(R.id.node_otp_container)
var otpProgress: ProgressBar? = itemView.findViewById(R.id.node_otp_progress) var otpProgress: ProgressBar? = itemView.findViewById(R.id.node_otp_progress)

View File

@@ -177,16 +177,20 @@ class Group : Node, GroupVersionedInterface<Group, Entry> {
fun addChildrenFrom(group: Group) { fun addChildrenFrom(group: Group) {
group.groupKDB?.getChildEntries()?.forEach { entryToAdd -> group.groupKDB?.getChildEntries()?.forEach { entryToAdd ->
groupKDB?.addChildEntry(entryToAdd) groupKDB?.addChildEntry(entryToAdd)
entryToAdd.parent = groupKDB
} }
group.groupKDB?.getChildGroups()?.forEach { groupToAdd -> group.groupKDB?.getChildGroups()?.forEach { groupToAdd ->
groupKDB?.addChildGroup(groupToAdd) groupKDB?.addChildGroup(groupToAdd)
groupToAdd.parent = groupKDB
} }
group.groupKDBX?.getChildEntries()?.forEach { entryToAdd -> group.groupKDBX?.getChildEntries()?.forEach { entryToAdd ->
groupKDBX?.addChildEntry(entryToAdd) groupKDBX?.addChildEntry(entryToAdd)
entryToAdd.parent = groupKDBX
} }
group.groupKDBX?.getChildGroups()?.forEach { groupToAdd -> group.groupKDBX?.getChildGroups()?.forEach { groupToAdd ->
groupKDBX?.addChildGroup(groupToAdd) groupKDBX?.addChildGroup(groupToAdd)
groupToAdd.parent = groupKDBX
} }
} }

View File

@@ -272,7 +272,7 @@ class MagikeyboardService : InputMethodService(), KeyboardView.OnKeyboardActionL
if (entryInfoKey != null) { if (entryInfoKey != null) {
currentInputConnection.commitText(entryInfoKey!!.url, 1) currentInputConnection.commitText(entryInfoKey!!.url, 1)
} }
actionTabAutomatically() actionGoAutomatically()
} }
KEY_FIELDS -> { KEY_FIELDS -> {
if (entryInfoKey != null) { if (entryInfoKey != null) {

View File

@@ -64,11 +64,13 @@ class DurationDialogFragmentCompat : InputPreferenceDialogFragmentCompat() {
private fun durationToDaysHoursMinutesSeconds(duration: Long) { private fun durationToDaysHoursMinutesSeconds(duration: Long) {
if (duration < 0) { if (duration < 0) {
mEnabled = false
mDays = 0 mDays = 0
mHours = 0 mHours = 0
mMinutes = 0 mMinutes = 0
mSeconds = 0 mSeconds = 0
} else { } else {
mEnabled = true
mDays = (duration / (24L * 60L * 60L * 1000L)).toInt() mDays = (duration / (24L * 60L * 60L * 1000L)).toInt()
val daysMilliseconds = mDays * 24L * 60L * 60L * 1000L val daysMilliseconds = mDays * 24L * 60L * 60L * 1000L
mHours = ((duration - daysMilliseconds) / (60L * 60L * 1000L)).toInt() mHours = ((duration - daysMilliseconds) / (60L * 60L * 1000L)).toInt()
@@ -125,10 +127,9 @@ class DurationDialogFragmentCompat : InputPreferenceDialogFragmentCompat() {
} }
} }
mEnabled = isSwitchActivated()
setSwitchAction({ isChecked -> setSwitchAction({ isChecked ->
mEnabled = isChecked mEnabled = isChecked
}, mDays + mHours + mMinutes + mSeconds > 0) }, mEnabled)
assignValuesInViews() assignValuesInViews()
} }

View File

@@ -275,22 +275,26 @@ abstract class TemplateAbstractView<
templateAttribute: TemplateAttribute, templateAttribute: TemplateAttribute,
entryInfoValue: String, entryInfoValue: String,
showEmptyFields: Boolean) { showEmptyFields: Boolean) {
var fieldView: TEntryFieldView? = findViewWithTag(fieldTag) try {
if (!showEmptyFields && entryInfoValue.isEmpty()) { var fieldView: TEntryFieldView? = findViewWithTag(fieldTag)
fieldView?.isFieldVisible = false if (!showEmptyFields && entryInfoValue.isEmpty()) {
} else if (fieldView == null && entryInfoValue.isNotEmpty()) { fieldView?.isFieldVisible = false
// Add new not referenced view if standard field not in template } else if (fieldView == null && entryInfoValue.isNotEmpty()) {
fieldView = buildViewForNotReferencedField( // Add new not referenced view if standard field not in template
Field(templateAttribute.label, fieldView = buildViewForNotReferencedField(
ProtectedString(templateAttribute.protected, "")), Field(templateAttribute.label,
templateAttribute ProtectedString(templateAttribute.protected, "")),
) as? TEntryFieldView? templateAttribute
fieldView?.let { ) as? TEntryFieldView?
addNotReferencedView(it as View) fieldView?.let {
addNotReferencedView(it as View)
}
} }
fieldView?.value = entryInfoValue
fieldView?.applyFontVisibility(mFontInVisibility)
} catch(e: Exception) {
Log.e(TAG, "Unable to populate entry field view", e)
} }
fieldView?.value = entryInfoValue
fieldView?.applyFontVisibility(mFontInVisibility)
} }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@@ -299,22 +303,25 @@ abstract class TemplateAbstractView<
expires: Boolean, expires: Boolean,
expiryTime: DateInstant, expiryTime: DateInstant,
showEmptyFields: Boolean) { showEmptyFields: Boolean) {
try {
var fieldView: TDateTimeView? = findViewWithTag(fieldTag) var fieldView: TDateTimeView? = findViewWithTag(fieldTag)
if (!showEmptyFields && !expires) { if (!showEmptyFields && !expires) {
fieldView?.isFieldVisible = false fieldView?.isFieldVisible = false
} else if (fieldView == null && expires) { } else if (fieldView == null && expires) {
fieldView = buildViewForNotReferencedField( fieldView = buildViewForNotReferencedField(
Field(templateAttribute.label, Field(templateAttribute.label,
ProtectedString(templateAttribute.protected, "")), ProtectedString(templateAttribute.protected, "")),
templateAttribute templateAttribute
) as? TDateTimeView? ) as? TDateTimeView?
fieldView?.let { fieldView?.let {
addNotReferencedView(it as View) addNotReferencedView(it as View)
}
} }
fieldView?.activation = expires
fieldView?.dateTime = expiryTime
} catch(e: Exception) {
Log.e(TAG, "Unable to populate date time view", e)
} }
fieldView?.activation = expires
fieldView?.dateTime = expiryTime
} }
/** /**

View File

@@ -187,6 +187,6 @@ class TextEditFieldView @JvmOverloads constructor(context: Context,
companion object { companion object {
const val MAX_CHARS_LIMIT = Integer.MAX_VALUE const val MAX_CHARS_LIMIT = Integer.MAX_VALUE
const val MAX_LINES_LIMIT = 40 const val MAX_LINES_LIMIT = Integer.MAX_VALUE
} }
} }

View File

@@ -30,8 +30,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:minHeight="56dp" android:minHeight="48dp"
android:maxHeight="72dp"
app:layout_constraintWidth_percent="@dimen/content_percent" app:layout_constraintWidth_percent="@dimen/content_percent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
@@ -104,10 +103,12 @@
tools:text="7543A7EAB2EA7CFD1394F1615EBEB08C" /> tools:text="7543A7EAB2EA7CFD1394F1615EBEB08C" />
</LinearLayout> </LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout <LinearLayout
android:id="@+id/node_options" android:id="@+id/node_options"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="0dp" android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="end"
android:layout_marginStart="12dp" android:layout_marginStart="12dp"
android:layout_marginLeft="12dp" android:layout_marginLeft="12dp"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@@ -164,7 +165,7 @@
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/node_otp_container" /> app:layout_constraintTop_toBottomOf="@+id/node_otp_container" />
</androidx.constraintlayout.widget.ConstraintLayout> </LinearLayout>
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@@ -30,8 +30,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:minHeight="56dp" android:minHeight="48dp"
android:maxHeight="72dp"
app:layout_constraintWidth_percent="@dimen/content_percent" app:layout_constraintWidth_percent="@dimen/content_percent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
@@ -89,18 +88,6 @@
android:maxLines="2" android:maxLines="2"
tools:text="Node Title" /> tools:text="Node Title" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/node_subtext"
style="@style/KeepassDXStyle.TextAppearance.Group.SubTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="-4dp"
android:gravity="center_vertical"
android:lines="1"
android:singleLine="true"
android:visibility="gone"
tools:text="Node SubTitle" />
<androidx.appcompat.widget.AppCompatTextView <androidx.appcompat.widget.AppCompatTextView
android:id="@+id/node_meta" android:id="@+id/node_meta"
style="@style/KeepassDXStyle.TextAppearance.Group.Meta" style="@style/KeepassDXStyle.TextAppearance.Group.Meta"

View File

@@ -367,7 +367,7 @@
<string name="clipboard_warning">If automatic deletion of clipboard fails, delete its history manually.</string> <string name="clipboard_warning">If automatic deletion of clipboard fails, delete its history manually.</string>
<string name="lock">Lock</string> <string name="lock">Lock</string>
<string name="lock_database_screen_off_title">Screen lock</string> <string name="lock_database_screen_off_title">Screen lock</string>
<string name="lock_database_screen_off_summary">Lock the database when the screen is off</string> <string name="lock_database_screen_off_summary">Lock the database after a few seconds once the screen is off</string>
<string name="lock_database_back_root_title">Press \'Back\' to lock</string> <string name="lock_database_back_root_title">Press \'Back\' to lock</string>
<string name="lock_database_back_root_summary">Lock the database when the user clicks the back button on the root screen</string> <string name="lock_database_back_root_summary">Lock the database when the user clicks the back button on the root screen</string>
<string name="lock_database_show_button_title">Show lock button</string> <string name="lock_database_show_button_title">Show lock button</string>

View File

@@ -0,0 +1,7 @@
* Fix text size and smallest margin #1085
* Fix number of lines during an edition #1073
* Fix Magikeyboard URL auto action #1100
* Fix exception after group name change and save #1112
* Fix timeout reset #1107
* Fix search actions #1091 #1092
* Small changes #1106 #1085

View File

@@ -0,0 +1,7 @@
* Correction de la taille de texte et plus petites marges #1085
* Correction du nombre de lignes d'édition #1073
* Correction de l'action auto de l'URL Magiclavier #1100
* Correction de l'exception après un changement de nom de groupe et sauvegarde #1112
* Correction de la réinitialisation du délai d'expiration #1107
* Correction des actions de recherche #1091 #1092
* Petits changements #1106 #1085