mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4f2a1eb89 | ||
|
|
e9fc9cbc2a | ||
|
|
b809180a1b | ||
|
|
ecc75df3a1 | ||
|
|
d1b6863143 | ||
|
|
faf27143aa | ||
|
|
aee58a4475 | ||
|
|
c5e07f643f | ||
|
|
818f5820d5 | ||
|
|
77c6e28876 | ||
|
|
fb7f66012d | ||
|
|
0f7f7bbe6c | ||
|
|
8dedb8deb4 | ||
|
|
d284db4d3c |
@@ -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)
|
||||
* Add / Manage dynamic templates #191
|
||||
* Manually select RecycleBin group and Templates group #191
|
||||
|
||||
@@ -11,8 +11,8 @@ android {
|
||||
applicationId "com.kunzisoft.keepass"
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 30
|
||||
versionCode = 87
|
||||
versionName = "3.0.0"
|
||||
versionCode = 88
|
||||
versionName = "3.0.1"
|
||||
multiDexEnabled true
|
||||
|
||||
testApplicationId = "com.kunzisoft.keepass.tests"
|
||||
|
||||
@@ -653,6 +653,8 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
Log.e(TAG, "Node can't be cast in Entry")
|
||||
}
|
||||
}
|
||||
|
||||
reloadGroupIfSearch()
|
||||
}
|
||||
|
||||
private fun entrySelectedForSave(database: Database, entry: Entry, searchInfo: SearchInfo) {
|
||||
@@ -738,6 +740,12 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
actionNodeMode?.finish()
|
||||
}
|
||||
|
||||
private fun reloadGroupIfSearch() {
|
||||
if (Intent.ACTION_SEARCH == intent.action) {
|
||||
reloadCurrentGroup()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNodeSelected(
|
||||
database: Database,
|
||||
nodes: List<Node>
|
||||
@@ -793,6 +801,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
(node as Entry).nodeId
|
||||
)
|
||||
}
|
||||
reloadGroupIfSearch()
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -847,6 +856,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
): Boolean {
|
||||
deleteNodes(nodes)
|
||||
finishNodeAction()
|
||||
reloadGroupIfSearch()
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -1093,7 +1103,7 @@ class GroupActivity : DatabaseLockActivity(),
|
||||
try {
|
||||
mGroupViewModel.loadGroup(mDatabase, mCurrentGroupState)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Unable to rebuild the list after deletion", e)
|
||||
Log.e(TAG, "Unable to rebuild the group", e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,8 +67,10 @@ class NodeAdapter (private val context: Context,
|
||||
private var mCalculateViewTypeTextSize = Array(2) { true } // number of view type
|
||||
private var mTextSizeUnit: Int = TypedValue.COMPLEX_UNIT_PX
|
||||
private var mPrefSizeMultiplier: Float = 0F
|
||||
private var mSubtextDefaultDimension: Float = 0F
|
||||
private var mInfoTextDefaultDimension: Float = 0F
|
||||
private var mTextDefaultDimension: Float = 0F
|
||||
private var mSubTextDefaultDimension: Float = 0F
|
||||
private var mMetaTextDefaultDimension: Float = 0F
|
||||
private var mOtpTokenTextDefaultDimension: Float = 0F
|
||||
private var mNumberChildrenTextDefaultDimension: 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)
|
||||
}
|
||||
val nodeViewHolder = NodeViewHolder(view)
|
||||
mInfoTextDefaultDimension = nodeViewHolder.text.textSize
|
||||
mSubtextDefaultDimension = nodeViewHolder.subText.textSize
|
||||
mTextDefaultDimension = nodeViewHolder.text.textSize
|
||||
mSubTextDefaultDimension = nodeViewHolder.subText?.textSize ?: mSubTextDefaultDimension
|
||||
mMetaTextDefaultDimension = nodeViewHolder.meta.textSize
|
||||
mOtpTokenTextDefaultDimension = nodeViewHolder.otpToken?.textSize ?: mOtpTokenTextDefaultDimension
|
||||
nodeViewHolder.numberChildren?.let {
|
||||
mNumberChildrenTextDefaultDimension = it.textSize
|
||||
}
|
||||
@@ -315,7 +319,9 @@ class NodeAdapter (private val context: Context,
|
||||
val subNode = mNodeSortedList.get(position)
|
||||
|
||||
// Node selection
|
||||
holder.container.isSelected = mActionNodesList.contains(subNode)
|
||||
holder.container.apply {
|
||||
isSelected = mActionNodesList.contains(subNode)
|
||||
}
|
||||
|
||||
// Assign image
|
||||
val iconColor = if (holder.container.isSelected)
|
||||
@@ -337,19 +343,18 @@ class NodeAdapter (private val context: Context,
|
||||
// Assign text
|
||||
holder.text.apply {
|
||||
text = subNode.title
|
||||
setTextSize(mTextSizeUnit, mInfoTextDefaultDimension, mPrefSizeMultiplier)
|
||||
setTextSize(mTextSizeUnit, mTextDefaultDimension, mPrefSizeMultiplier)
|
||||
strikeOut(subNode.isCurrentlyExpires)
|
||||
}
|
||||
// Add subText with username
|
||||
holder.subText.apply {
|
||||
text = ""
|
||||
strikeOut(subNode.isCurrentlyExpires)
|
||||
visibility = View.GONE
|
||||
}
|
||||
// Add meta text to show UUID
|
||||
holder.meta.apply {
|
||||
text = subNode.nodeId.toString()
|
||||
visibility = if (mShowUUID) View.VISIBLE else View.GONE
|
||||
if (mShowUUID) {
|
||||
text = subNode.nodeId.toString()
|
||||
setTextSize(mTextSizeUnit, mMetaTextDefaultDimension, mPrefSizeMultiplier)
|
||||
visibility = View.VISIBLE
|
||||
} else {
|
||||
visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
// Specific elements for entry
|
||||
@@ -358,12 +363,16 @@ class NodeAdapter (private val context: Context,
|
||||
database.startManageEntry(entry)
|
||||
|
||||
holder.text.text = entry.getVisualTitle()
|
||||
holder.subText.apply {
|
||||
// Add subText with username
|
||||
holder.subText?.apply {
|
||||
val username = entry.username
|
||||
if (mShowUserNames && username.isNotEmpty()) {
|
||||
visibility = View.VISIBLE
|
||||
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 {
|
||||
otpElement?.token?.let { token ->
|
||||
Toast.makeText(
|
||||
@@ -483,7 +495,7 @@ class NodeAdapter (private val context: Context,
|
||||
var imageIdentifier: ImageView? = itemView.findViewById(R.id.node_image_identifier)
|
||||
var icon: ImageView = itemView.findViewById(R.id.node_icon)
|
||||
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 otpContainer: ViewGroup? = itemView.findViewById(R.id.node_otp_container)
|
||||
var otpProgress: ProgressBar? = itemView.findViewById(R.id.node_otp_progress)
|
||||
|
||||
@@ -177,16 +177,20 @@ class Group : Node, GroupVersionedInterface<Group, Entry> {
|
||||
fun addChildrenFrom(group: Group) {
|
||||
group.groupKDB?.getChildEntries()?.forEach { entryToAdd ->
|
||||
groupKDB?.addChildEntry(entryToAdd)
|
||||
entryToAdd.parent = groupKDB
|
||||
}
|
||||
group.groupKDB?.getChildGroups()?.forEach { groupToAdd ->
|
||||
groupKDB?.addChildGroup(groupToAdd)
|
||||
groupToAdd.parent = groupKDB
|
||||
}
|
||||
|
||||
group.groupKDBX?.getChildEntries()?.forEach { entryToAdd ->
|
||||
groupKDBX?.addChildEntry(entryToAdd)
|
||||
entryToAdd.parent = groupKDBX
|
||||
}
|
||||
group.groupKDBX?.getChildGroups()?.forEach { groupToAdd ->
|
||||
groupKDBX?.addChildGroup(groupToAdd)
|
||||
groupToAdd.parent = groupKDBX
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -272,7 +272,7 @@ class MagikeyboardService : InputMethodService(), KeyboardView.OnKeyboardActionL
|
||||
if (entryInfoKey != null) {
|
||||
currentInputConnection.commitText(entryInfoKey!!.url, 1)
|
||||
}
|
||||
actionTabAutomatically()
|
||||
actionGoAutomatically()
|
||||
}
|
||||
KEY_FIELDS -> {
|
||||
if (entryInfoKey != null) {
|
||||
|
||||
@@ -64,11 +64,13 @@ class DurationDialogFragmentCompat : InputPreferenceDialogFragmentCompat() {
|
||||
|
||||
private fun durationToDaysHoursMinutesSeconds(duration: Long) {
|
||||
if (duration < 0) {
|
||||
mEnabled = false
|
||||
mDays = 0
|
||||
mHours = 0
|
||||
mMinutes = 0
|
||||
mSeconds = 0
|
||||
} else {
|
||||
mEnabled = true
|
||||
mDays = (duration / (24L * 60L * 60L * 1000L)).toInt()
|
||||
val daysMilliseconds = mDays * 24L * 60L * 60L * 1000L
|
||||
mHours = ((duration - daysMilliseconds) / (60L * 60L * 1000L)).toInt()
|
||||
@@ -125,10 +127,9 @@ class DurationDialogFragmentCompat : InputPreferenceDialogFragmentCompat() {
|
||||
}
|
||||
}
|
||||
|
||||
mEnabled = isSwitchActivated()
|
||||
setSwitchAction({ isChecked ->
|
||||
mEnabled = isChecked
|
||||
}, mDays + mHours + mMinutes + mSeconds > 0)
|
||||
}, mEnabled)
|
||||
|
||||
assignValuesInViews()
|
||||
}
|
||||
|
||||
@@ -275,22 +275,26 @@ abstract class TemplateAbstractView<
|
||||
templateAttribute: TemplateAttribute,
|
||||
entryInfoValue: String,
|
||||
showEmptyFields: Boolean) {
|
||||
var fieldView: TEntryFieldView? = findViewWithTag(fieldTag)
|
||||
if (!showEmptyFields && entryInfoValue.isEmpty()) {
|
||||
fieldView?.isFieldVisible = false
|
||||
} else if (fieldView == null && entryInfoValue.isNotEmpty()) {
|
||||
// Add new not referenced view if standard field not in template
|
||||
fieldView = buildViewForNotReferencedField(
|
||||
Field(templateAttribute.label,
|
||||
ProtectedString(templateAttribute.protected, "")),
|
||||
templateAttribute
|
||||
) as? TEntryFieldView?
|
||||
fieldView?.let {
|
||||
addNotReferencedView(it as View)
|
||||
try {
|
||||
var fieldView: TEntryFieldView? = findViewWithTag(fieldTag)
|
||||
if (!showEmptyFields && entryInfoValue.isEmpty()) {
|
||||
fieldView?.isFieldVisible = false
|
||||
} else if (fieldView == null && entryInfoValue.isNotEmpty()) {
|
||||
// Add new not referenced view if standard field not in template
|
||||
fieldView = buildViewForNotReferencedField(
|
||||
Field(templateAttribute.label,
|
||||
ProtectedString(templateAttribute.protected, "")),
|
||||
templateAttribute
|
||||
) as? TEntryFieldView?
|
||||
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")
|
||||
@@ -299,22 +303,25 @@ abstract class TemplateAbstractView<
|
||||
expires: Boolean,
|
||||
expiryTime: DateInstant,
|
||||
showEmptyFields: Boolean) {
|
||||
|
||||
var fieldView: TDateTimeView? = findViewWithTag(fieldTag)
|
||||
if (!showEmptyFields && !expires) {
|
||||
fieldView?.isFieldVisible = false
|
||||
} else if (fieldView == null && expires) {
|
||||
fieldView = buildViewForNotReferencedField(
|
||||
Field(templateAttribute.label,
|
||||
ProtectedString(templateAttribute.protected, "")),
|
||||
templateAttribute
|
||||
) as? TDateTimeView?
|
||||
fieldView?.let {
|
||||
addNotReferencedView(it as View)
|
||||
try {
|
||||
var fieldView: TDateTimeView? = findViewWithTag(fieldTag)
|
||||
if (!showEmptyFields && !expires) {
|
||||
fieldView?.isFieldVisible = false
|
||||
} else if (fieldView == null && expires) {
|
||||
fieldView = buildViewForNotReferencedField(
|
||||
Field(templateAttribute.label,
|
||||
ProtectedString(templateAttribute.protected, "")),
|
||||
templateAttribute
|
||||
) as? TDateTimeView?
|
||||
fieldView?.let {
|
||||
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
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -187,6 +187,6 @@ class TextEditFieldView @JvmOverloads constructor(context: Context,
|
||||
|
||||
companion object {
|
||||
const val MAX_CHARS_LIMIT = Integer.MAX_VALUE
|
||||
const val MAX_LINES_LIMIT = 40
|
||||
const val MAX_LINES_LIMIT = Integer.MAX_VALUE
|
||||
}
|
||||
}
|
||||
@@ -30,8 +30,7 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:minHeight="56dp"
|
||||
android:maxHeight="72dp"
|
||||
android:minHeight="48dp"
|
||||
app:layout_constraintWidth_percent="@dimen/content_percent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
@@ -104,10 +103,12 @@
|
||||
tools:text="7543A7EAB2EA7CFD1394F1615EBEB08C" />
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
<LinearLayout
|
||||
android:id="@+id/node_options"
|
||||
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_marginLeft="12dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
@@ -164,7 +165,7 @@
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/node_otp_container" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -30,8 +30,7 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:minHeight="56dp"
|
||||
android:maxHeight="72dp"
|
||||
android:minHeight="48dp"
|
||||
app:layout_constraintWidth_percent="@dimen/content_percent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
@@ -89,18 +88,6 @@
|
||||
android:maxLines="2"
|
||||
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
|
||||
android:id="@+id/node_meta"
|
||||
style="@style/KeepassDXStyle.TextAppearance.Group.Meta"
|
||||
|
||||
@@ -367,7 +367,7 @@
|
||||
<string name="clipboard_warning">If automatic deletion of clipboard fails, delete its history manually.</string>
|
||||
<string name="lock">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_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>
|
||||
|
||||
7
fastlane/metadata/android/en-US/changelogs/88.txt
Normal file
7
fastlane/metadata/android/en-US/changelogs/88.txt
Normal 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
|
||||
7
fastlane/metadata/android/fr-FR/changelogs/88.txt
Normal file
7
fastlane/metadata/android/fr-FR/changelogs/88.txt
Normal 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
|
||||
Reference in New Issue
Block a user