mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Compare commits
23 Commits
2.5.0.0bet
...
2.5.0.0bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2781af38d | ||
|
|
a1cd2683d4 | ||
|
|
6d671f53c2 | ||
|
|
4efb81f597 | ||
|
|
faddeb6e2d | ||
|
|
e36629968d | ||
|
|
0b756797f6 | ||
|
|
110c7bbbc7 | ||
|
|
639c6dc4ac | ||
|
|
f605d36adf | ||
|
|
f6d6c134f4 | ||
|
|
a0c07654df | ||
|
|
03ab688abe | ||
|
|
4a28802b02 | ||
|
|
18f8fe7cc3 | ||
|
|
459606f5d5 | ||
|
|
3d53c31680 | ||
|
|
173dd5b59b | ||
|
|
8536de3555 | ||
|
|
722ba5c34d | ||
|
|
3ccfd7226b | ||
|
|
578da7bae5 | ||
|
|
6916389657 |
@@ -1,3 +1,11 @@
|
||||
KeepassDX (2.5.0.0beta21)
|
||||
* Fix nested groups no longer visible in V1 databases
|
||||
* Improved data import algorithm for V1 databases
|
||||
* Add natural database sort
|
||||
* Add username database sort
|
||||
* Fix button disabled with only KeyFile
|
||||
* Show the number of entries in a group
|
||||
|
||||
KeepassDX (2.5.0.0beta20)
|
||||
* Fix a major bug that displays an entry history
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ android {
|
||||
applicationId "com.kunzisoft.keepass"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 27
|
||||
versionCode = 20
|
||||
versionName = "2.5.0.0beta20"
|
||||
versionCode = 21
|
||||
versionName = "2.5.0.0beta21"
|
||||
multiDexEnabled true
|
||||
|
||||
testApplicationId = "com.kunzisoft.keepass.tests"
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.activities.stylish.StylishFragment
|
||||
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
|
||||
class ListNodesFragment : StylishFragment(), SortDialogFragment.SortSelectionListener {
|
||||
|
||||
@@ -205,24 +206,20 @@ class ListNodesFragment : StylishFragment(), SortDialogFragment.SortSelectionLis
|
||||
|
||||
R.id.menu_sort -> {
|
||||
context?.let { context ->
|
||||
val sortDialogFragment: SortDialogFragment
|
||||
|
||||
/*
|
||||
// TODO Recycle bin bottom
|
||||
if (database.isRecycleBinAvailable() && database.isRecycleBinEnabled()) {
|
||||
sortDialogFragment =
|
||||
val sortDialogFragment: SortDialogFragment =
|
||||
if (Database.getInstance().isRecycleBinAvailable
|
||||
&& Database.getInstance().isRecycleBinEnabled) {
|
||||
SortDialogFragment.getInstance(
|
||||
PrefsUtil.getListSort(this),
|
||||
PrefsUtil.getAscendingSort(this),
|
||||
PrefsUtil.getGroupsBeforeSort(this),
|
||||
PrefsUtil.getRecycleBinBottomSort(this));
|
||||
PreferencesUtil.getListSort(context),
|
||||
PreferencesUtil.getAscendingSort(context),
|
||||
PreferencesUtil.getGroupsBeforeSort(context),
|
||||
PreferencesUtil.getRecycleBinBottomSort(context))
|
||||
} else {
|
||||
*/
|
||||
sortDialogFragment = SortDialogFragment.getInstance(
|
||||
SortDialogFragment.getInstance(
|
||||
PreferencesUtil.getListSort(context),
|
||||
PreferencesUtil.getAscendingSort(context),
|
||||
PreferencesUtil.getGroupsBeforeSort(context))
|
||||
//}
|
||||
}
|
||||
|
||||
sortDialogFragment.show(childFragmentManager, "sortDialog")
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@ import com.kunzisoft.keepass.activities.dialogs.PasswordEncodingDialogFragment
|
||||
import com.kunzisoft.keepass.activities.helpers.*
|
||||
import com.kunzisoft.keepass.activities.lock.LockingActivity
|
||||
import com.kunzisoft.keepass.activities.stylish.StylishActivity
|
||||
import com.kunzisoft.keepass.app.App
|
||||
import com.kunzisoft.keepass.autofill.AutofillHelper
|
||||
import com.kunzisoft.keepass.database.action.LoadDatabaseRunnable
|
||||
import com.kunzisoft.keepass.database.action.ProgressDialogThread
|
||||
@@ -148,10 +147,8 @@ class PasswordActivity : StylishActivity(),
|
||||
}
|
||||
})
|
||||
|
||||
enableButtonOnCheckedChangeListener = CompoundButton.OnCheckedChangeListener { _, isChecked ->
|
||||
if (!PreferencesUtil.emptyPasswordAllowed(this@PasswordActivity)) {
|
||||
confirmButtonView?.isEnabled = isChecked
|
||||
}
|
||||
enableButtonOnCheckedChangeListener = CompoundButton.OnCheckedChangeListener { _, _ ->
|
||||
enableOrNotTheConfirmationButton()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,15 +172,6 @@ class PasswordActivity : StylishActivity(),
|
||||
// For check shutdown
|
||||
super.onResume()
|
||||
|
||||
// Enable or not the open button
|
||||
if (!PreferencesUtil.emptyPasswordAllowed(this@PasswordActivity)) {
|
||||
checkboxPasswordView?.let {
|
||||
confirmButtonView?.isEnabled = it.isChecked
|
||||
}
|
||||
} else {
|
||||
confirmButtonView?.isEnabled = true
|
||||
}
|
||||
|
||||
UriIntentInitTask(WeakReference(this), this, mRememberKeyFile)
|
||||
.execute(intent)
|
||||
}
|
||||
@@ -288,6 +276,21 @@ class PasswordActivity : StylishActivity(),
|
||||
if (!fingerPrintInit) {
|
||||
checkboxPasswordView?.setOnCheckedChangeListener(enableButtonOnCheckedChangeListener)
|
||||
}
|
||||
checkboxKeyFileView?.setOnCheckedChangeListener(enableButtonOnCheckedChangeListener)
|
||||
}
|
||||
|
||||
enableOrNotTheConfirmationButton()
|
||||
}
|
||||
|
||||
private fun enableOrNotTheConfirmationButton() {
|
||||
// Enable or not the open button if setting is checked
|
||||
if (!PreferencesUtil.emptyPasswordAllowed(this@PasswordActivity)) {
|
||||
checkboxPasswordView?.let {
|
||||
confirmButtonView?.isEnabled = (checkboxPasswordView?.isChecked == true
|
||||
|| checkboxKeyFileView?.isChecked == true)
|
||||
}
|
||||
} else {
|
||||
confirmButtonView?.isEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,12 +35,12 @@ class SortDialogFragment : DialogFragment() {
|
||||
|
||||
private var mListener: SortSelectionListener? = null
|
||||
|
||||
private var mSortNodeEnum: SortNodeEnum? = null
|
||||
private var mSortNodeEnum: SortNodeEnum = SortNodeEnum.DB
|
||||
@IdRes
|
||||
private var mCheckedId: Int = 0
|
||||
private var mGroupsBefore: Boolean = false
|
||||
private var mAscending: Boolean = false
|
||||
private var mRecycleBinBottom: Boolean = false
|
||||
private var mGroupsBefore: Boolean = true
|
||||
private var mAscending: Boolean = true
|
||||
private var mRecycleBinBottom: Boolean = true
|
||||
|
||||
override fun onAttach(context: Context?) {
|
||||
super.onAttach(context)
|
||||
@@ -50,18 +50,13 @@ class SortDialogFragment : DialogFragment() {
|
||||
throw ClassCastException(context!!.toString()
|
||||
+ " must implement " + SortSelectionListener::class.java.name)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
activity?.let { activity ->
|
||||
val builder = AlertDialog.Builder(activity)
|
||||
|
||||
mSortNodeEnum = SortNodeEnum.TITLE
|
||||
mAscending = true
|
||||
mGroupsBefore = true
|
||||
var recycleBinAllowed = false
|
||||
mRecycleBinBottom = true
|
||||
|
||||
arguments?.apply {
|
||||
if (containsKey(SORT_NODE_ENUM_BUNDLE_KEY))
|
||||
|
||||
@@ -30,7 +30,6 @@ import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.app.App
|
||||
import com.kunzisoft.keepass.database.SortNodeEnum
|
||||
import com.kunzisoft.keepass.database.element.*
|
||||
import com.kunzisoft.keepass.icons.assignDatabaseIcon
|
||||
@@ -48,11 +47,14 @@ class NodeAdapter
|
||||
private val inflater: LayoutInflater = LayoutInflater.from(context)
|
||||
private var textSize: Float = 0.toFloat()
|
||||
private var subtextSize: Float = 0.toFloat()
|
||||
private var infoTextSize: Float = 0.toFloat()
|
||||
private var iconSize: Float = 0.toFloat()
|
||||
private var listSort: SortNodeEnum? = null
|
||||
private var groupsBeforeSort: Boolean = false
|
||||
private var ascendingSort: Boolean = false
|
||||
private var showUserNames: Boolean = false
|
||||
private var listSort: SortNodeEnum = SortNodeEnum.DB
|
||||
private var ascendingSort: Boolean = true
|
||||
private var groupsBeforeSort: Boolean = true
|
||||
private var recycleBinBottomSort: Boolean = true
|
||||
private var showUserNames: Boolean = true
|
||||
private var showNumberEntries: Boolean = true
|
||||
|
||||
private var nodeClickCallback: NodeClickCallback? = null
|
||||
private var nodeMenuListener: NodeMenuListener? = null
|
||||
@@ -80,7 +82,7 @@ class NodeAdapter
|
||||
|
||||
this.nodeSortedList = SortedList(NodeVersioned::class.java, object : SortedListAdapterCallback<NodeVersioned>(this) {
|
||||
override fun compare(item1: NodeVersioned, item2: NodeVersioned): Int {
|
||||
return listSort?.getNodeComparator(ascendingSort, groupsBeforeSort)?.compare(item1, item2) ?: 0
|
||||
return listSort.getNodeComparator(ascendingSort, groupsBeforeSort, recycleBinBottomSort).compare(item1, item2)
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: NodeVersioned, newItem: NodeVersioned): Boolean {
|
||||
@@ -121,13 +123,16 @@ class NodeAdapter
|
||||
val textSizeDefault = java.lang.Float.parseFloat(context.getString(R.string.list_size_default))
|
||||
this.textSize = PreferencesUtil.getListTextSize(context)
|
||||
this.subtextSize = context.resources.getInteger(R.integer.list_small_size_default) * textSize / textSizeDefault
|
||||
this.infoTextSize = context.resources.getInteger(R.integer.list_tiny_size_default) * textSize / textSizeDefault
|
||||
// Retrieve the icon size
|
||||
val iconDefaultSize = context.resources.getDimension(R.dimen.list_icon_size_default)
|
||||
this.iconSize = iconDefaultSize * textSize / textSizeDefault
|
||||
this.listSort = PreferencesUtil.getListSort(context)
|
||||
this.groupsBeforeSort = PreferencesUtil.getGroupsBeforeSort(context)
|
||||
this.ascendingSort = PreferencesUtil.getAscendingSort(context)
|
||||
this.groupsBeforeSort = PreferencesUtil.getGroupsBeforeSort(context)
|
||||
this.recycleBinBottomSort = PreferencesUtil.getRecycleBinBottomSort(context)
|
||||
this.showUserNames = PreferencesUtil.showUsernamesListEntries(context)
|
||||
this.showNumberEntries = PreferencesUtil.showNumberEntries(context)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,14 +141,12 @@ class NodeAdapter
|
||||
fun rebuildList(group: GroupVersioned) {
|
||||
this.nodeSortedList.clear()
|
||||
assignPreferences()
|
||||
// TODO verify sort
|
||||
try {
|
||||
this.nodeSortedList.addAll(group.getChildrenWithoutMetaStream())
|
||||
this.nodeSortedList.addAll(group.getChildren())
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Can't add node elements to the list", e)
|
||||
Toast.makeText(context, "Can't add node elements to the list : " + e.message, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,6 +242,17 @@ class NodeAdapter
|
||||
holder.icon.layoutParams?.width = iconSize.toInt()
|
||||
holder.text.textSize = textSize
|
||||
holder.subText.textSize = subtextSize
|
||||
if (subNode.type == Type.GROUP) {
|
||||
if (showNumberEntries) {
|
||||
holder.numberChildren?.apply {
|
||||
text = (subNode as GroupVersioned).getChildEntries().size.toString()
|
||||
textSize = infoTextSize
|
||||
visibility = View.VISIBLE
|
||||
}
|
||||
} else {
|
||||
holder.numberChildren?.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
@@ -356,6 +370,7 @@ class NodeAdapter
|
||||
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 numberChildren: TextView? = itemView.findViewById(R.id.node_child_numbers)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -20,41 +20,54 @@
|
||||
|
||||
package com.kunzisoft.keepass.database
|
||||
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.element.EntryVersioned
|
||||
import com.kunzisoft.keepass.database.element.GroupVersioned
|
||||
import com.kunzisoft.keepass.database.element.NodeVersioned
|
||||
|
||||
import java.util.Comparator
|
||||
import com.kunzisoft.keepass.database.element.Type
|
||||
import java.util.*
|
||||
|
||||
enum class SortNodeEnum {
|
||||
DB, TITLE, USERNAME, CREATION_TIME, LAST_MODIFY_TIME, LAST_ACCESS_TIME;
|
||||
|
||||
fun getNodeComparator(ascending: Boolean, groupsBefore: Boolean): Comparator<NodeVersioned> {
|
||||
fun getNodeComparator(ascending: Boolean, groupsBefore: Boolean, recycleBinBottom: Boolean): Comparator<NodeVersioned> {
|
||||
return when (this) {
|
||||
DB -> NodeCreationComparator(ascending, groupsBefore) // TODO Sort
|
||||
TITLE -> NodeTitleComparator(ascending, groupsBefore)
|
||||
USERNAME -> NodeCreationComparator(ascending, groupsBefore) // TODO Sort
|
||||
CREATION_TIME -> NodeCreationComparator(ascending, groupsBefore)
|
||||
LAST_MODIFY_TIME -> NodeLastModificationComparator(ascending, groupsBefore)
|
||||
LAST_ACCESS_TIME -> NodeLastAccessComparator(ascending, groupsBefore)
|
||||
DB -> NodeNaturalComparator(ascending, groupsBefore, recycleBinBottom)
|
||||
TITLE -> NodeTitleComparator(ascending, groupsBefore, recycleBinBottom)
|
||||
USERNAME -> NodeUsernameComparator(ascending, groupsBefore, recycleBinBottom)
|
||||
CREATION_TIME -> NodeCreationComparator(ascending, groupsBefore, recycleBinBottom)
|
||||
LAST_MODIFY_TIME -> NodeLastModificationComparator(ascending, groupsBefore, recycleBinBottom)
|
||||
LAST_ACCESS_TIME -> NodeLastAccessComparator(ascending, groupsBefore, recycleBinBottom)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class NodeComparator internal constructor(internal var ascending: Boolean, private var groupsBefore: Boolean) : Comparator<NodeVersioned> {
|
||||
abstract class NodeComparator(var ascending: Boolean, var groupsBefore: Boolean, var recycleBinBottom: Boolean) : Comparator<NodeVersioned> {
|
||||
|
||||
internal fun compareWith(comparatorGroup: Comparator<GroupVersioned>,
|
||||
comparatorEntry: Comparator<EntryVersioned>,
|
||||
object1: NodeVersioned,
|
||||
object2: NodeVersioned,
|
||||
resultOfNodeMethodCompare: Int): Int {
|
||||
abstract fun compareBySpecificOrder(object1: NodeVersioned, object2: NodeVersioned): Int
|
||||
|
||||
private fun specificOrderOrHashIfEquals(object1: NodeVersioned, object2: NodeVersioned): Int {
|
||||
val specificOrderComp = compareBySpecificOrder(object1, object2)
|
||||
|
||||
return if (specificOrderComp == 0) {
|
||||
object1.hashCode() - object2.hashCode()
|
||||
} else if (!ascending) -specificOrderComp else specificOrderComp // If descending, revert
|
||||
}
|
||||
|
||||
override fun compare(object1: NodeVersioned,object2: NodeVersioned): Int {
|
||||
if (object1 == object2)
|
||||
return 0
|
||||
|
||||
if (object1 is GroupVersioned) {
|
||||
return if (object2 is GroupVersioned) {
|
||||
comparatorGroup
|
||||
.compare(object1, object2)
|
||||
} else if (object2 is EntryVersioned) {
|
||||
if (object1.type == Type.GROUP) {
|
||||
return if (object2.type == Type.GROUP) {
|
||||
// RecycleBin at end of groups
|
||||
if (recycleBinBottom) {
|
||||
if (Database.getInstance().recycleBin == object1)
|
||||
return 1
|
||||
if (Database.getInstance().recycleBin == object2)
|
||||
return -1
|
||||
}
|
||||
|
||||
specificOrderOrHashIfEquals(object1, object2)
|
||||
} else if (object2.type == Type.ENTRY) {
|
||||
if (groupsBefore)
|
||||
-1
|
||||
else
|
||||
@@ -62,11 +75,10 @@ enum class SortNodeEnum {
|
||||
} else {
|
||||
-1
|
||||
}
|
||||
} else if (object1 is EntryVersioned) {
|
||||
return if (object2 is EntryVersioned) {
|
||||
comparatorEntry
|
||||
.compare(object1, object2)
|
||||
} else if (object2 is GroupVersioned) {
|
||||
} else if (object1.type == Type.ENTRY) {
|
||||
return if (object2.type == Type.ENTRY) {
|
||||
specificOrderOrHashIfEquals(object1, object2)
|
||||
} else if (object2.type == Type.GROUP) {
|
||||
if (groupsBefore)
|
||||
1
|
||||
else
|
||||
@@ -76,235 +88,83 @@ enum class SortNodeEnum {
|
||||
}
|
||||
}
|
||||
|
||||
// If same name, can be different
|
||||
return if (resultOfNodeMethodCompare == 0) object1.hashCode() - object2.hashCode() else resultOfNodeMethodCompare
|
||||
// Type not known
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator of Node by Title, Groups first, Entries second
|
||||
* Comparator of node by natural database placement
|
||||
*/
|
||||
class NodeTitleComparator internal constructor(ascending: Boolean, groupsBefore: Boolean) : NodeComparator(ascending, groupsBefore) {
|
||||
class NodeNaturalComparator(ascending: Boolean, groupsBefore: Boolean, recycleBinBottom: Boolean)
|
||||
: NodeComparator(ascending, groupsBefore, recycleBinBottom) {
|
||||
|
||||
override fun compare(object1: NodeVersioned, object2: NodeVersioned): Int {
|
||||
|
||||
return compareWith(
|
||||
GroupNameComparator(ascending),
|
||||
EntryNameComparator(ascending),
|
||||
object1,
|
||||
object2,
|
||||
object1.title
|
||||
.compareTo(object2.title, ignoreCase = true))
|
||||
override fun compareBySpecificOrder(object1: NodeVersioned, object2: NodeVersioned): Int {
|
||||
return object1.nodePositionInParent.compareTo(object2.nodePositionInParent)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator of node by creation, Groups first, Entries second
|
||||
* Comparator of Node by Title
|
||||
*/
|
||||
class NodeCreationComparator internal constructor(ascending: Boolean, groupsBefore: Boolean) : NodeComparator(ascending, groupsBefore) {
|
||||
class NodeTitleComparator(ascending: Boolean, groupsBefore: Boolean, recycleBinBottom: Boolean)
|
||||
: NodeComparator(ascending, groupsBefore, recycleBinBottom) {
|
||||
|
||||
override fun compare(object1: NodeVersioned, object2: NodeVersioned): Int {
|
||||
|
||||
return compareWith(
|
||||
GroupCreationComparator(ascending),
|
||||
EntryCreationComparator(ascending),
|
||||
object1,
|
||||
object2,
|
||||
object1.creationTime.date
|
||||
?.compareTo(object2.creationTime.date) ?: 0)
|
||||
override fun compareBySpecificOrder(object1: NodeVersioned, object2: NodeVersioned): Int {
|
||||
return object1.title.compareTo(object2.title, ignoreCase = true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator of node by last modification, Groups first, Entries second
|
||||
* Comparator of Node by Username, Groups by title
|
||||
*/
|
||||
class NodeLastModificationComparator internal constructor(ascending: Boolean, groupsBefore: Boolean) : NodeComparator(ascending, groupsBefore) {
|
||||
class NodeUsernameComparator(ascending: Boolean, groupsBefore: Boolean, recycleBinBottom: Boolean)
|
||||
: NodeComparator(ascending, groupsBefore, recycleBinBottom) {
|
||||
|
||||
override fun compare(object1: NodeVersioned, object2: NodeVersioned): Int {
|
||||
|
||||
return compareWith(
|
||||
GroupLastModificationComparator(ascending),
|
||||
EntryLastModificationComparator(ascending),
|
||||
object1,
|
||||
object2,
|
||||
object1.lastModificationTime.date
|
||||
?.compareTo(object2.lastModificationTime.date) ?: 0)
|
||||
override fun compareBySpecificOrder(object1: NodeVersioned, object2: NodeVersioned): Int {
|
||||
if (object1.type == Type.ENTRY && object2.type == Type.ENTRY) {
|
||||
// To get username if it's a ref
|
||||
return (object1 as EntryVersioned).getEntryInfo(Database.getInstance()).username
|
||||
.compareTo((object2 as EntryVersioned).getEntryInfo(Database.getInstance()).username,
|
||||
ignoreCase = true)
|
||||
}
|
||||
return NodeTitleComparator(ascending, groupsBefore, recycleBinBottom).compare(object1, object2)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator of node by last access, Groups first, Entries second
|
||||
* Comparator of node by creation
|
||||
*/
|
||||
class NodeLastAccessComparator internal constructor(ascending: Boolean, groupsBefore: Boolean) : NodeComparator(ascending, groupsBefore) {
|
||||
class NodeCreationComparator(ascending: Boolean, groupsBefore: Boolean, recycleBinBottom: Boolean)
|
||||
: NodeComparator(ascending, groupsBefore, recycleBinBottom) {
|
||||
|
||||
override fun compare(object1: NodeVersioned, object2: NodeVersioned): Int {
|
||||
|
||||
return compareWith(
|
||||
GroupLastAccessComparator(ascending),
|
||||
EntryLastAccessComparator(ascending),
|
||||
object1,
|
||||
object2,
|
||||
object1.lastAccessTime.date
|
||||
?.compareTo(object2.lastAccessTime.date) ?: 0)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AscendingComparator<Node> internal constructor(private val ascending: Boolean) : Comparator<Node> {
|
||||
|
||||
internal fun compareWithAscending(basicCompareResult: Int): Int {
|
||||
// If descending, revert
|
||||
return if (!ascending) -basicCompareResult else basicCompareResult
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Group comparator by name
|
||||
*/
|
||||
class GroupNameComparator internal constructor(ascending: Boolean) : AscendingComparator<GroupVersioned>(ascending) {
|
||||
|
||||
override fun compare(object1: GroupVersioned, object2: GroupVersioned): Int {
|
||||
if (object1 == object2)
|
||||
return 0
|
||||
|
||||
val groupNameComp = object1.title.compareTo(object2.title, ignoreCase = true)
|
||||
// If same name, can be different
|
||||
return if (groupNameComp == 0) {
|
||||
object1.hashCode() - object2.hashCode()
|
||||
} else compareWithAscending(groupNameComp)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Group comparator by name
|
||||
*/
|
||||
class GroupCreationComparator internal constructor(ascending: Boolean) : AscendingComparator<GroupVersioned>(ascending) {
|
||||
|
||||
override fun compare(object1: GroupVersioned, object2: GroupVersioned): Int {
|
||||
if (object1 == object2)
|
||||
return 0
|
||||
|
||||
val groupCreationComp = object1.creationTime.date
|
||||
override fun compareBySpecificOrder(object1: NodeVersioned, object2: NodeVersioned): Int {
|
||||
return object1.creationTime.date
|
||||
?.compareTo(object2.creationTime.date) ?: 0
|
||||
// If same creation, can be different
|
||||
return if (groupCreationComp == 0) {
|
||||
object1.hashCode() - object2.hashCode()
|
||||
} else compareWithAscending(groupCreationComp)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Group comparator by last modification
|
||||
* Comparator of node by last modification
|
||||
*/
|
||||
class GroupLastModificationComparator internal constructor(ascending: Boolean) : AscendingComparator<GroupVersioned>(ascending) {
|
||||
class NodeLastModificationComparator(ascending: Boolean, groupsBefore: Boolean, recycleBinBottom: Boolean)
|
||||
: NodeComparator(ascending, groupsBefore, recycleBinBottom) {
|
||||
|
||||
override fun compare(object1: GroupVersioned, object2: GroupVersioned): Int {
|
||||
if (object1 == object2)
|
||||
return 0
|
||||
|
||||
val groupLastModificationComp = object1.lastModificationTime.date
|
||||
override fun compareBySpecificOrder(object1: NodeVersioned, object2: NodeVersioned): Int {
|
||||
return object1.lastModificationTime.date
|
||||
?.compareTo(object2.lastModificationTime.date) ?: 0
|
||||
// If same creation, can be different
|
||||
return if (groupLastModificationComp == 0) {
|
||||
object1.hashCode() - object2.hashCode()
|
||||
} else compareWithAscending(groupLastModificationComp)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Group comparator by last access
|
||||
* Comparator of node by last access
|
||||
*/
|
||||
class GroupLastAccessComparator internal constructor(ascending: Boolean) : AscendingComparator<GroupVersioned>(ascending) {
|
||||
class NodeLastAccessComparator(ascending: Boolean, groupsBefore: Boolean, recycleBinBottom: Boolean)
|
||||
: NodeComparator(ascending, groupsBefore, recycleBinBottom) {
|
||||
|
||||
override fun compare(object1: GroupVersioned, object2: GroupVersioned): Int {
|
||||
if (object1 == object2)
|
||||
return 0
|
||||
|
||||
val groupLastAccessComp = object1.lastAccessTime.date
|
||||
override fun compareBySpecificOrder(object1: NodeVersioned, object2: NodeVersioned): Int {
|
||||
return object1.lastAccessTime.date
|
||||
?.compareTo(object2.lastAccessTime.date) ?: 0
|
||||
// If same creation, can be different
|
||||
return if (groupLastAccessComp == 0) {
|
||||
object1.hashCode() - object2.hashCode()
|
||||
} else compareWithAscending(groupLastAccessComp)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator of Entry by Name
|
||||
*/
|
||||
class EntryNameComparator internal constructor(ascending: Boolean) : AscendingComparator<EntryVersioned>(ascending) {
|
||||
|
||||
override fun compare(object1: EntryVersioned, object2: EntryVersioned): Int {
|
||||
if (object1 == object2)
|
||||
return 0
|
||||
|
||||
val entryTitleComp = object1.title.compareTo(object2.title, ignoreCase = true)
|
||||
// If same title, can be different
|
||||
return if (entryTitleComp == 0) {
|
||||
object1.hashCode() - object2.hashCode()
|
||||
} else compareWithAscending(entryTitleComp)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator of Entry by Creation
|
||||
*/
|
||||
class EntryCreationComparator internal constructor(ascending: Boolean) : AscendingComparator<EntryVersioned>(ascending) {
|
||||
|
||||
override fun compare(object1: EntryVersioned, object2: EntryVersioned): Int {
|
||||
if (object1 == object2)
|
||||
return 0
|
||||
|
||||
val entryCreationComp = object1.creationTime.date
|
||||
?.compareTo(object2.creationTime.date) ?: 0
|
||||
// If same creation, can be different
|
||||
return if (entryCreationComp == 0) {
|
||||
object1.hashCode() - object2.hashCode()
|
||||
} else compareWithAscending(entryCreationComp)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator of Entry by Last Modification
|
||||
*/
|
||||
class EntryLastModificationComparator internal constructor(ascending: Boolean) : AscendingComparator<EntryVersioned>(ascending) {
|
||||
|
||||
override fun compare(object1: EntryVersioned, object2: EntryVersioned): Int {
|
||||
if (object1 == object2)
|
||||
return 0
|
||||
|
||||
val entryLastModificationComp = object1.lastModificationTime.date
|
||||
?.compareTo(object2.lastModificationTime.date) ?: 0
|
||||
// If same creation, can be different
|
||||
return if (entryLastModificationComp == 0) {
|
||||
object1.hashCode() - object2.hashCode()
|
||||
} else compareWithAscending(entryLastModificationComp)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator of Entry by Last Access
|
||||
*/
|
||||
class EntryLastAccessComparator internal constructor(ascending: Boolean) : AscendingComparator<EntryVersioned>(ascending) {
|
||||
|
||||
override fun compare(object1: EntryVersioned, object2: EntryVersioned): Int {
|
||||
if (object1 == object2)
|
||||
return 0
|
||||
|
||||
val entryLastAccessComp = object1.lastAccessTime.date
|
||||
?.compareTo(object2.lastAccessTime.date) ?: 0
|
||||
// If same creation, can be different
|
||||
return if (entryLastAccessComp == 0) {
|
||||
object1.hashCode() - object2.hashCode()
|
||||
} else compareWithAscending(entryLastAccessComp)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,11 +338,24 @@ class EntryVersioned : NodeVersioned, PwEntryInterface<GroupVersioned> {
|
||||
return entryInfo
|
||||
}
|
||||
|
||||
/*
|
||||
------------
|
||||
Class methods
|
||||
------------
|
||||
*/
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as EntryVersioned
|
||||
|
||||
if (pwEntryV3 != other.pwEntryV3) return false
|
||||
if (pwEntryV4 != other.pwEntryV4) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = pwEntryV3?.hashCode() ?: 0
|
||||
result = 31 * result + (pwEntryV4?.hashCode() ?: 0)
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<EntryVersioned> {
|
||||
override fun createFromParcel(parcel: Parcel): EntryVersioned {
|
||||
|
||||
@@ -195,12 +195,15 @@ class GroupVersioned : NodeVersioned, PwGroupInterface<GroupVersioned, EntryVers
|
||||
* Filter MetaStream entries and return children
|
||||
* @return List of direct children (one level below) as PwNode
|
||||
*/
|
||||
fun getChildrenWithoutMetaStream(): List<NodeVersioned> {
|
||||
fun getChildren(withoutMetaStream: Boolean = true): List<NodeVersioned> {
|
||||
val children = ArrayList<NodeVersioned>()
|
||||
children.addAll(getChildGroups())
|
||||
|
||||
pwGroupV3?.let {
|
||||
if (withoutMetaStream)
|
||||
children.addAll(getChildEntries().filter { !it.isMetaStream })
|
||||
else
|
||||
children.addAll(getChildEntries())
|
||||
}
|
||||
pwGroupV4?.let {
|
||||
// No MetasStream in V4
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
package com.kunzisoft.keepass.database.element
|
||||
|
||||
interface NodeVersioned: PwNodeInterface<GroupVersioned>
|
||||
interface NodeVersioned: PwNodeInterface<GroupVersioned> {
|
||||
|
||||
val nodePositionInParent: Int
|
||||
get() {
|
||||
parent?.getChildren(false)?.let { children ->
|
||||
for ((i, child) in children.withIndex()) {
|
||||
if (child == this)
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Type of available Nodes
|
||||
|
||||
@@ -27,7 +27,6 @@ import java.io.InputStream
|
||||
import java.security.DigestOutputStream
|
||||
import java.security.MessageDigest
|
||||
import java.security.NoSuchAlgorithmException
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* @author Naomaru Itoi <nao></nao>@phoneid.org>
|
||||
@@ -76,53 +75,6 @@ class PwDatabaseV3 : PwDatabase<PwGroupV3, PwEntryV3>() {
|
||||
numKeyEncRounds = DEFAULT_ENCRYPTION_ROUNDS
|
||||
}
|
||||
|
||||
private fun assignGroupsChildren(parent: PwGroupV3) {
|
||||
val levelToCheck = parent.level + 1
|
||||
var startFromParentPosition = false
|
||||
for (groupToCheck in getGroupIndexes()) {
|
||||
rootGroup?.let { root ->
|
||||
if (root.nodeId == parent.nodeId || groupToCheck.nodeId == parent.nodeId) {
|
||||
startFromParentPosition = true
|
||||
}
|
||||
}
|
||||
if (startFromParentPosition) {
|
||||
if (groupToCheck.level < levelToCheck)
|
||||
break
|
||||
else if (groupToCheck.level == levelToCheck)
|
||||
parent.addChildGroup(groupToCheck)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignEntriesChildren(parent: PwGroupV3) {
|
||||
for (entry in getEntryIndexes()) {
|
||||
if (entry.parent!!.nodeId == parent.nodeId)
|
||||
parent.addChildEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
private fun constructTreeFromIndex(currentGroup: PwGroupV3) {
|
||||
|
||||
assignGroupsChildren(currentGroup)
|
||||
assignEntriesChildren(currentGroup)
|
||||
|
||||
// set parent in child entries (normally useless but to be sure or to update parent metadata)
|
||||
for (childEntry in currentGroup.getChildEntries()) {
|
||||
childEntry.parent = currentGroup
|
||||
}
|
||||
// recursively construct child groups
|
||||
for (childGroup in currentGroup.getChildGroups()) {
|
||||
childGroup.parent = currentGroup
|
||||
constructTreeFromIndex(childGroup)
|
||||
}
|
||||
}
|
||||
|
||||
fun constructTreeFromIndex() {
|
||||
rootGroup?.let {
|
||||
constructTreeFromIndex(it)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an unused random tree id
|
||||
*
|
||||
|
||||
@@ -268,10 +268,6 @@ class PwEntryV4 : PwEntry<PwGroupV4, PwEntryV4>, NodeV4Interface {
|
||||
binaries[key] = value
|
||||
}
|
||||
|
||||
fun addToHistory(entry: PwEntryV4) {
|
||||
history.add(entry)
|
||||
}
|
||||
|
||||
fun sizeOfHistory(): Int {
|
||||
return history.size
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.kunzisoft.keepass.database.element
|
||||
|
||||
import android.os.Parcel
|
||||
import java.util.*
|
||||
|
||||
abstract class PwGroup
|
||||
<
|
||||
@@ -13,9 +12,9 @@ abstract class PwGroup
|
||||
|
||||
private var titleGroup = ""
|
||||
@Transient
|
||||
private val childGroups = ArrayList<Group>()
|
||||
private val childGroups = LinkedHashSet<Group>()
|
||||
@Transient
|
||||
private val childEntries = ArrayList<Entry>()
|
||||
private val childEntries = LinkedHashSet<Entry>()
|
||||
|
||||
constructor() : super()
|
||||
|
||||
@@ -31,6 +30,8 @@ abstract class PwGroup
|
||||
protected fun updateWith(source: PwGroup<Id, Group, Entry>) {
|
||||
super.updateWith(source)
|
||||
titleGroup = source.titleGroup
|
||||
childGroups.addAll(source.childGroups)
|
||||
childEntries.addAll(source.childEntries)
|
||||
}
|
||||
|
||||
override var title: String
|
||||
@@ -38,18 +39,20 @@ abstract class PwGroup
|
||||
set(value) { titleGroup = value }
|
||||
|
||||
override fun getChildGroups(): MutableList<Group> {
|
||||
return childGroups
|
||||
return childGroups.toMutableList()
|
||||
}
|
||||
|
||||
override fun getChildEntries(): MutableList<Entry> {
|
||||
return childEntries
|
||||
return childEntries.toMutableList()
|
||||
}
|
||||
|
||||
override fun addChildGroup(group: Group) {
|
||||
// TODO duplicate UUID
|
||||
this.childGroups.add(group)
|
||||
}
|
||||
|
||||
override fun addChildEntry(entry: Entry) {
|
||||
// TODO duplicate UUID
|
||||
this.childEntries.add(entry)
|
||||
}
|
||||
|
||||
|
||||
@@ -68,9 +68,6 @@ import java.util.Arrays
|
||||
|
||||
/**
|
||||
* Load a v3 database file.
|
||||
*
|
||||
* @author Naomaru Itoi <nao></nao>@phoneid.org>
|
||||
* @author Bill Zwicky <wrzwicky></wrzwicky>@pobox.com>
|
||||
*/
|
||||
class ImporterV3 : Importer<PwDatabaseV3>() {
|
||||
|
||||
@@ -223,11 +220,52 @@ class ImporterV3 : Importer<PwDatabaseV3>() {
|
||||
pos += 2 + 4 + fieldSize
|
||||
}
|
||||
|
||||
mDatabaseToOpen.constructTreeFromIndex()
|
||||
constructTreeFromIndex()
|
||||
|
||||
return mDatabaseToOpen
|
||||
}
|
||||
|
||||
private fun buildTreeGroups(previousGroup: PwGroupV3, currentGroup: PwGroupV3, groupIterator: Iterator<PwGroupV3>) {
|
||||
|
||||
if (currentGroup.parent == null && (previousGroup.level + 1) == currentGroup.level) {
|
||||
// Current group has an increment level compare to the previous, current group is a child
|
||||
previousGroup.addChildGroup(currentGroup)
|
||||
currentGroup.parent = previousGroup
|
||||
} else if (previousGroup.parent != null && previousGroup.level == currentGroup.level) {
|
||||
// In the same level, previous parent is the same as previous group
|
||||
previousGroup.parent!!.addChildGroup(currentGroup)
|
||||
currentGroup.parent = previousGroup.parent
|
||||
} else if (previousGroup.parent != null) {
|
||||
// Previous group has a higher level than the current group, check it's parent
|
||||
buildTreeGroups(previousGroup.parent!!, currentGroup, groupIterator)
|
||||
}
|
||||
|
||||
// Next current group
|
||||
if (groupIterator.hasNext()){
|
||||
buildTreeGroups(currentGroup, groupIterator.next(), groupIterator)
|
||||
}
|
||||
}
|
||||
|
||||
private fun constructTreeFromIndex() {
|
||||
mDatabaseToOpen.rootGroup?.let {
|
||||
|
||||
// add each group
|
||||
val groupIterator = mDatabaseToOpen.getGroupIndexes().iterator()
|
||||
if (groupIterator.hasNext())
|
||||
buildTreeGroups(it, groupIterator.next(), groupIterator)
|
||||
|
||||
// add each child
|
||||
for (currentEntry in mDatabaseToOpen.getEntryIndexes()) {
|
||||
if (currentEntry.parent != null) {
|
||||
// Only the parent id is known so complete the info
|
||||
val parentGroupRetrieve = mDatabaseToOpen.getGroupById(currentEntry.parent!!.nodeId)
|
||||
parentGroupRetrieve?.addChildEntry(currentEntry)
|
||||
currentEntry.parent = parentGroupRetrieve
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse and save one record from binary file.
|
||||
* @param buf
|
||||
|
||||
@@ -533,7 +533,6 @@ class ImporterV4(private val streamDir: File) : Importer<PwDatabaseV4>() {
|
||||
|
||||
KdbContext.Entry -> if (name.equals(PwDatabaseV4XML.ElemUuid, ignoreCase = true)) {
|
||||
ctxEntry?.nodeId = PwNodeIdUUID(readUuid(xpp))
|
||||
ctxEntry?.let { mDatabase.addEntryIndex(it) }
|
||||
} else if (name.equals(PwDatabaseV4XML.ElemIcon, ignoreCase = true)) {
|
||||
ctxEntry?.icon = mDatabase.iconFactory.getIcon(readUInt(xpp, 0).toInt())
|
||||
} else if (name.equals(PwDatabaseV4XML.ElemCustomIconID, ignoreCase = true)) {
|
||||
@@ -633,7 +632,7 @@ class ImporterV4(private val streamDir: File) : Importer<PwDatabaseV4>() {
|
||||
|
||||
KdbContext.EntryHistory -> if (name.equals(PwDatabaseV4XML.ElemEntry, ignoreCase = true)) {
|
||||
ctxEntry = PwEntryV4()
|
||||
ctxEntry?.let { ctxHistoryBase?.addToHistory(it) }
|
||||
ctxEntry?.let { ctxHistoryBase?.addEntryToHistory(it) }
|
||||
|
||||
entryInHistory = true
|
||||
return switchContext(ctx, KdbContext.Entry, xpp)
|
||||
@@ -731,15 +730,18 @@ class ImporterV4(private val streamDir: File) : Importer<PwDatabaseV4>() {
|
||||
return KdbContext.GroupCustomData
|
||||
|
||||
} else if (ctx == KdbContext.Entry && name.equals(PwDatabaseV4XML.ElemEntry, ignoreCase = true)) {
|
||||
if (ctxEntry != null && ctxEntry?.id == PwDatabase.UUID_ZERO) {
|
||||
|
||||
if (ctxEntry?.id == PwDatabase.UUID_ZERO)
|
||||
ctxEntry?.nodeId = mDatabase.newEntryId()
|
||||
mDatabase.addEntryIndex(ctxEntry!!)
|
||||
}
|
||||
|
||||
if (entryInHistory) {
|
||||
ctxEntry = ctxHistoryBase
|
||||
return KdbContext.EntryHistory
|
||||
}
|
||||
else if (ctxEntry != null) {
|
||||
// Add entry to the index only when close the XML element
|
||||
mDatabase.addEntryIndex(ctxEntry!!)
|
||||
}
|
||||
|
||||
return KdbContext.Group
|
||||
} else if (ctx == KdbContext.EntryTimes && name.equals(PwDatabaseV4XML.ElemTimes, ignoreCase = true)) {
|
||||
|
||||
@@ -40,6 +40,12 @@ object PreferencesUtil {
|
||||
context.resources.getBoolean(R.bool.list_entries_show_username_default))
|
||||
}
|
||||
|
||||
fun showNumberEntries(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.list_groups_show_number_entries_key),
|
||||
context.resources.getBoolean(R.bool.list_groups_show_number_entries_default))
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the text size in SP, verify the integrity of the size stored in preference
|
||||
*/
|
||||
@@ -130,7 +136,7 @@ object PreferencesUtil {
|
||||
fun getListSort(context: Context): SortNodeEnum {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
prefs.getString(context.getString(R.string.sort_node_key),
|
||||
SortNodeEnum.TITLE.name)?.let {
|
||||
SortNodeEnum.DB.name)?.let {
|
||||
return SortNodeEnum.valueOf(it)
|
||||
}
|
||||
return SortNodeEnum.DB
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<item>
|
||||
<shape
|
||||
android:shape="oval">
|
||||
<stroke android:color="?attr/colorAccent" android:width="2dp"/>
|
||||
<stroke android:color="?attr/colorAccent" android:width="1dp"/>
|
||||
<padding
|
||||
android:left="12dp"
|
||||
android:right="12dp"
|
||||
|
||||
@@ -6,11 +6,6 @@
|
||||
<item>
|
||||
<shape>
|
||||
<stroke android:color="?attr/colorAccent" android:width="1dp"/>
|
||||
<padding
|
||||
android:left="12dp"
|
||||
android:right="12dp"
|
||||
android:top="12dp"
|
||||
android:bottom="12dp"/>
|
||||
<solid android:color="@color/transparent"/>
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<item android:state_pressed="true">
|
||||
<shape
|
||||
android:shape="oval">
|
||||
<stroke android:color="@color/orange_light" android:width="2dp"/>
|
||||
<stroke android:color="@color/orange_light" android:width="1dp"/>
|
||||
<padding
|
||||
android:left="12dp"
|
||||
android:right="12dp"
|
||||
@@ -15,7 +15,7 @@
|
||||
<item>
|
||||
<shape
|
||||
android:shape="oval">
|
||||
<stroke android:color="@color/orange" android:width="2dp"/>
|
||||
<stroke android:color="@color/orange" android:width="1dp"/>
|
||||
<padding
|
||||
android:left="12dp"
|
||||
android:right="12dp"
|
||||
|
||||
@@ -3,11 +3,6 @@
|
||||
<item>
|
||||
<shape>
|
||||
<stroke android:color="@color/orange" android:width="1dp"/>
|
||||
<padding
|
||||
android:left="12dp"
|
||||
android:right="12dp"
|
||||
android:top="12dp"
|
||||
android:bottom="12dp"/>
|
||||
<solid android:color="@color/transparent"/>
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
14
app/src/main/res/drawable/background_text_info.xml
Normal file
14
app/src/main/res/drawable/background_text_info.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape>
|
||||
<corners android:radius="25dp" />
|
||||
<padding
|
||||
android:left="4dp"
|
||||
android:right="4dp"
|
||||
android:top="1dp"
|
||||
android:bottom="1dp"/>
|
||||
<solid android:color="@color/orange"/>
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
||||
@@ -65,6 +65,7 @@
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:src="@drawable/ic_save_white_24dp"
|
||||
android:contentDescription="@string/content_description_entry_save"
|
||||
app:useCompatPadding="true"
|
||||
style="@style/KeepassDXStyle.Fab"/>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
@@ -197,21 +197,17 @@
|
||||
|
||||
<android.support.v7.widget.AppCompatImageView
|
||||
android:id="@+id/file_select_expandable_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:elevation="8dp"
|
||||
app:layout_constraintTop_toTopOf="@+id/browse_button"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/browse_button"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:focusable="true"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:padding="12dp"
|
||||
android:tint="?attr/textColorInverse"
|
||||
android:src="@drawable/ic_link_white_24dp"/>
|
||||
android:src="@drawable/ic_link_white_24dp"
|
||||
android:contentDescription="@string/content_description_show_file_link"/>
|
||||
|
||||
<net.cachapa.expandablelayout.ExpandableLayout
|
||||
android:id="@+id/file_select_expandable"
|
||||
@@ -226,39 +222,36 @@
|
||||
android:id="@+id/file_select"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorPrimaryDark"
|
||||
android:paddingLeft="@dimen/default_margin"
|
||||
android:paddingStart="@dimen/default_margin"
|
||||
android:paddingRight="@dimen/default_margin"
|
||||
android:paddingEnd="@dimen/default_margin">
|
||||
android:background="?attr/colorPrimaryDark">
|
||||
|
||||
<android.support.v7.widget.AppCompatEditText
|
||||
android:id="@+id/file_filename"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp"
|
||||
android:inputType="textUri"
|
||||
android:textColor="?attr/textColorInverse"
|
||||
android:textColorHint="?attr/android:textColorHintInverse"
|
||||
android:layout_toLeftOf="@+id/open_database"
|
||||
android:layout_toStartOf="@+id/open_database"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:layout_marginStart="2dp"
|
||||
android:layout_marginLeft="2dp"
|
||||
android:layout_marginRight="2dp"
|
||||
android:layout_marginEnd="2dp"
|
||||
android:layout_marginLeft="@dimen/default_margin"
|
||||
android:layout_marginStart="@dimen/default_margin"
|
||||
android:layout_marginRight="@dimen/default_margin"
|
||||
android:layout_marginEnd="@dimen/default_margin"
|
||||
android:maxLines="1"/>
|
||||
|
||||
<android.support.v7.widget.AppCompatImageView
|
||||
android:id="@+id/open_database"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:padding="12dp"
|
||||
android:layout_alignTop="@+id/file_filename"
|
||||
android:layout_alignBottom="@+id/file_filename"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:focusable="true"
|
||||
android:src="@drawable/ic_send_white_24dp"
|
||||
android:contentDescription="@string/content_description_open_file_link"
|
||||
android:tint="?attr/textColorInverse"/>
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
android:id="@+id/default_database"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp"
|
||||
android:layout_gravity="end"
|
||||
style="@style/KeepassDXStyle.TextAppearance.Small"
|
||||
android:textColor="?android:attr/textColorHintInverse"
|
||||
@@ -61,7 +62,6 @@
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:text="@string/default_checkbox" />
|
||||
<com.kunzisoft.keepass.view.FingerPrintInfoView
|
||||
android:id="@+id/fingerprint_info"
|
||||
@@ -128,6 +128,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="20dp"
|
||||
android:contentDescription="@string/content_description_password_checkbox"
|
||||
android:focusable="false"
|
||||
android:layout_alignBottom="@+id/password_input_layout"
|
||||
android:gravity="center_vertical" />
|
||||
@@ -165,6 +166,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="20dp"
|
||||
android:contentDescription="@string/content_description_keyfile_checkbox"
|
||||
android:focusable="false"
|
||||
android:layout_alignBottom="@+id/input_entry_keyfile"
|
||||
android:gravity="center_vertical" />
|
||||
@@ -192,12 +194,13 @@
|
||||
|
||||
<android.support.v7.widget.AppCompatImageView
|
||||
android:id="@+id/browse_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:padding="12dp"
|
||||
android:layout_alignBottom="@+id/input_entry_keyfile"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:padding="8dp"
|
||||
android:contentDescription="@string/content_description_open_file"
|
||||
android:focusable="true"
|
||||
android:src="@drawable/ic_folder_white_24dp"
|
||||
android:tint="?attr/colorAccent" />
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="6dp"
|
||||
android:contentDescription="@string/content_description_open_file"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignBottom="@+id/folder_path_input_layout"
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<EditText android:id="@+id/password"
|
||||
<EditText
|
||||
android:id="@+id/password"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
@@ -41,14 +42,17 @@
|
||||
android:hint="@string/hint_generated_password"
|
||||
tools:ignore="TextFields" />
|
||||
|
||||
<Button android:id="@+id/generate_password_button"
|
||||
<Button
|
||||
android:id="@+id/generate_password_button"
|
||||
android:layout_margin="@dimen/button_margin"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp"
|
||||
android:text="@string/generate_password" />
|
||||
</LinearLayout>
|
||||
|
||||
<ScrollView android:id="@+id/ScrollView"
|
||||
<ScrollView
|
||||
android:id="@+id/ScrollView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
@@ -61,12 +65,14 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView android:id="@+id/length_label"
|
||||
<TextView
|
||||
android:id="@+id/length_label"
|
||||
android:text="@string/length"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent" />
|
||||
|
||||
<EditText android:id="@+id/length"
|
||||
<EditText
|
||||
android:id="@+id/length"
|
||||
android:layout_width="50dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
@@ -78,7 +84,8 @@
|
||||
android:text="@string/default_password_length"
|
||||
android:hint="@string/hint_length"/>
|
||||
|
||||
<android.support.v7.widget.AppCompatSeekBar android:id="@+id/seekbar_length"
|
||||
<android.support.v7.widget.AppCompatSeekBar
|
||||
android:id="@+id/seekbar_length"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBottom="@+id/length"
|
||||
@@ -87,13 +94,15 @@
|
||||
android:layout_alignTop="@+id/length"
|
||||
android:layout_toEndOf="@+id/length"
|
||||
android:layout_toRightOf="@+id/length"
|
||||
android:contentDescription="@string/content_description_password_length"
|
||||
app:min="@string/min_password_length"
|
||||
android:progress="@string/default_password_length"
|
||||
android:max="@string/max_password_length"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout android:id="@+id/RelativeLayout"
|
||||
<LinearLayout
|
||||
android:id="@+id/RelativeLayout"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:orientation="vertical"
|
||||
@@ -103,7 +112,8 @@
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<CheckBox android:id="@+id/cb_uppercase"
|
||||
<CheckBox
|
||||
android:id="@+id/cb_uppercase"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/uppercase"
|
||||
@@ -123,7 +133,8 @@
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<CheckBox android:id="@+id/cb_lowercase"
|
||||
<CheckBox
|
||||
android:id="@+id/cb_lowercase"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/lowercase"
|
||||
@@ -143,7 +154,8 @@
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<CheckBox android:id="@+id/cb_digits"
|
||||
<CheckBox
|
||||
android:id="@+id/cb_digits"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/digits"
|
||||
@@ -163,7 +175,8 @@
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<CheckBox android:id="@+id/cb_minus"
|
||||
<CheckBox
|
||||
android:id="@+id/cb_minus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/minus" />
|
||||
@@ -182,7 +195,8 @@
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<CheckBox android:id="@+id/cb_underline"
|
||||
<CheckBox
|
||||
android:id="@+id/cb_underline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/underline" />
|
||||
@@ -201,7 +215,8 @@
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<CheckBox android:id="@+id/cb_space"
|
||||
<CheckBox
|
||||
android:id="@+id/cb_space"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/space" />
|
||||
@@ -220,7 +235,8 @@
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<CheckBox android:id="@+id/cb_specials"
|
||||
<CheckBox
|
||||
android:id="@+id/cb_specials"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/special" />
|
||||
@@ -239,7 +255,8 @@
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<CheckBox android:id="@+id/cb_brackets"
|
||||
<CheckBox
|
||||
android:id="@+id/cb_brackets"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/brackets"
|
||||
@@ -260,7 +277,8 @@
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<CheckBox android:id="@+id/cb_extended"
|
||||
<CheckBox
|
||||
android:id="@+id/cb_extended"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/extended_ASCII"
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
</LinearLayout>
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/nodes_list"
|
||||
android:contentDescription="@string/content_description_node_children"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:attr/windowBackground" />
|
||||
|
||||
@@ -115,6 +115,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:contentDescription="@string/content_description_open_file"
|
||||
android:padding="12dp"
|
||||
android:src="@drawable/ic_folder_white_24dp"
|
||||
android:tint="?attr/colorAccent" />
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
<RadioButton android:id="@+id/sort_selection_db"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sort_db"
|
||||
android:visibility="gone"/>
|
||||
android:text="@string/sort_db"/>
|
||||
<RadioButton android:id="@+id/sort_selection_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -24,8 +23,7 @@
|
||||
<RadioButton android:id="@+id/sort_selection_username"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sort_username"
|
||||
android:visibility="gone"/>
|
||||
android:text="@string/sort_username"/>
|
||||
<RadioButton android:id="@+id/sort_selection_creation_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingRight="12dp"
|
||||
@@ -45,10 +45,12 @@
|
||||
android:paddingStart="12dp" />
|
||||
<android.support.v7.widget.AppCompatImageView
|
||||
android:id="@+id/file_information"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:padding="12dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/ic_info_white_24dp"
|
||||
android:contentDescription="@string/content_description_file_information"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:tint="?android:attr/textColorHintInverse"/>
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
<android.support.constraint.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/node_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
@@ -61,6 +62,7 @@
|
||||
android:id="@+id/node_text"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
tools:text="Node Title"
|
||||
android:lines="1"
|
||||
android:singleLine="true"
|
||||
style="@style/KeepassDXStyle.TextAppearance.Default" /> <!-- style override -->
|
||||
@@ -69,6 +71,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_marginTop="-4dp"
|
||||
tools:text="Node SubTitle"
|
||||
android:lines="1"
|
||||
android:singleLine="true"
|
||||
style="@style/KeepassDXStyle.TextAppearance.Secondary" /> <!-- style override -->
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
<android.support.constraint.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/node_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
@@ -57,6 +58,17 @@
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toRightOf="@+id/group_arrow"
|
||||
android:layout_toEndOf="@+id/group_arrow" />
|
||||
<TextView
|
||||
android:id="@+id/node_child_numbers"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="3"
|
||||
android:layout_marginEnd="-18dp"
|
||||
android:layout_marginRight="-18dp"
|
||||
style="@style/KeepassDXStyle.TextAppearance.Info"
|
||||
android:layout_toLeftOf="@+id/node_icon"
|
||||
android:layout_toStartOf="@+id/node_icon"
|
||||
android:layout_alignTop="@+id/node_icon" />
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -73,6 +85,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
tools:text="Node Title"
|
||||
android:lines="1"
|
||||
android:singleLine="true"
|
||||
style="@style/KeepassDXStyle.TextAppearance.Title" /> <!-- style override -->
|
||||
@@ -81,6 +94,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
tools:text="Node SubTitle"
|
||||
android:layout_marginTop="-4dp"
|
||||
android:lines="1"
|
||||
android:singleLine="true"
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_add_white_24dp"
|
||||
android:contentDescription="@string/content_description_add_node"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
@@ -43,6 +44,7 @@
|
||||
android:layout_marginRight="@dimen/image_button_margin"
|
||||
android:layout_marginEnd="@dimen/image_button_margin"
|
||||
android:src="@drawable/ic_key_white_24dp"
|
||||
android:contentDescription="@string/add_entry"
|
||||
android:theme="@style/KeepassDXStyle.Fab.White"
|
||||
app:fabSize="mini"
|
||||
app:useCompatPadding="true" />
|
||||
@@ -73,6 +75,7 @@
|
||||
android:layout_marginRight="@dimen/image_button_margin"
|
||||
android:layout_marginEnd="@dimen/image_button_margin"
|
||||
android:src="@drawable/ic_folder_white_24dp"
|
||||
android:contentDescription="@string/add_group"
|
||||
android:theme="@style/KeepassDXStyle.Fab.White"
|
||||
app:fabSize="mini"
|
||||
app:useCompatPadding="true" />
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="4dp"
|
||||
android:src="@drawable/ic_blank_32dp"
|
||||
android:contentDescription="@string/content_description_entry_icon"
|
||||
android:layout_gravity="center"/>
|
||||
|
||||
<!-- Title -->
|
||||
@@ -108,6 +109,7 @@
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
app:passwordToggleEnabled="true"
|
||||
android:contentDescription="@string/content_description_repeat_toggle_password_visibility"
|
||||
android:layout_toLeftOf="@+id/entry_edit_generate_button"
|
||||
android:layout_toStartOf="@+id/entry_edit_generate_button"
|
||||
android:layout_below="@+id/entry_edit_container_password">
|
||||
@@ -125,13 +127,15 @@
|
||||
|
||||
<android.support.v7.widget.AppCompatImageView
|
||||
android:id="@+id/entry_edit_generate_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:padding="12dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_margin="8dp"
|
||||
android:src="@drawable/ic_key_white_24dp"
|
||||
android:contentDescription="@string/content_description_password_generator"
|
||||
android:tint="?attr/colorAccent"/>
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -176,15 +180,14 @@
|
||||
android:orientation="vertical">
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
<android.support.v7.widget.AppCompatImageButton
|
||||
android:id="@+id/entry_edit_add_new_field"
|
||||
android:layout_width="30sp"
|
||||
android:layout_height="30sp"
|
||||
android:contentDescription="@string/add_string"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_add_white_24dp"
|
||||
android:contentDescription="@string/content_description_add_field"
|
||||
android:tint="?attr/colorAccent"
|
||||
android:scaleType="centerCrop"
|
||||
android:visibility="gone"/>
|
||||
android:scaleType="centerCrop"/>
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
@@ -22,8 +22,6 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:layout_marginBottom="@dimen/default_margin"
|
||||
android:importantForAutofill="noExcludeDescendants"
|
||||
android:background="@drawable/background_new_field"
|
||||
@@ -33,8 +31,11 @@
|
||||
android:id="@+id/title_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toLeftOf="@+id/entry_new_field_delete"
|
||||
android:layout_toStartOf="@+id/entry_new_field_delete">
|
||||
android:paddingTop="12dp"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingEnd="12dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/entry_new_field_label"
|
||||
@@ -49,13 +50,13 @@
|
||||
|
||||
<android.support.v7.widget.AppCompatImageView
|
||||
android:id="@+id/entry_new_field_delete"
|
||||
android:layout_margin="4dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:padding="12dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_close_white_24dp"
|
||||
android:contentDescription="@string/content_description_remove_field"
|
||||
android:tint="?attr/colorAccent" />
|
||||
|
||||
<android.support.v7.widget.SwitchCompat
|
||||
@@ -63,6 +64,7 @@
|
||||
style="@style/KeepassDXStyle.TextAppearance.Default"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp"
|
||||
android:layout_below="@+id/value_container"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:text="@string/protection" />
|
||||
@@ -71,6 +73,10 @@
|
||||
android:id="@+id/value_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:layout_below="@+id/title_container">
|
||||
|
||||
<EditText
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
<string name="about_homepage">الصفحة الرئيسية :</string>
|
||||
<string name="accept">قبول</string>
|
||||
<string name="add_group">إضافة مجموعة</string>
|
||||
<string name="add_string">إضافة سلسلة</string>
|
||||
<string name="encryption">التعمية</string>
|
||||
<string name="encryption_algorithm">خوارزمية التعمية</string>
|
||||
<string name="application">التطبيق</string>
|
||||
|
||||
@@ -179,7 +179,6 @@
|
||||
<item>Velký</item>
|
||||
</string-array>
|
||||
<string name="edit_entry">Upravit záznam</string>
|
||||
<string name="add_string">Přidat řetězec</string>
|
||||
<string name="encryption">Šifrování</string>
|
||||
<string name="key_derivation_function">Funkce pro tvorbu klíče</string>
|
||||
<string name="extended_ASCII">Rozšířené ASCII</string>
|
||||
|
||||
@@ -175,7 +175,6 @@
|
||||
<item>Stor</item>
|
||||
</string-array>
|
||||
<string name="edit_entry">Rediger post</string>
|
||||
<string name="add_string">Tilføj streng</string>
|
||||
<string name="encryption">Kryptering</string>
|
||||
<string name="key_derivation_function">Nøgleafledningsfunktion</string>
|
||||
<string name="extended_ASCII">Udvidet ASCII</string>
|
||||
|
||||
@@ -27,12 +27,11 @@
|
||||
<string name="accept">Akzeptieren</string>
|
||||
<string name="add_entry">Eintrag hinzufügen</string>
|
||||
<string name="add_group">Gruppe hinzufügen</string>
|
||||
<string name="add_string">Text hinzufügen</string>
|
||||
<string name="encryption_algorithm">Verschlüsselungsalgorithmus</string>
|
||||
<string name="app_timeout">App-Sperre</string>
|
||||
<string name="app_timeout_summary">Dauer der Inaktivität bis die App gesperrt wird</string>
|
||||
<string name="application">App</string>
|
||||
<string name="menu_app_settings">Einstellungen</string>
|
||||
<string name="menu_app_settings">App Einstellungen</string>
|
||||
<string name="beta_dontask">Nicht mehr anzeigen</string>
|
||||
<string name="brackets">Klammern</string>
|
||||
<string name="browser_intall_text">Durchsuchen Sie Ihre Dateien, indem Sie den OpenIntents File Manager installieren</string>
|
||||
|
||||
@@ -157,7 +157,6 @@ Spanish translation by José I. Paños. Updated by David García-Abad (23-09-201
|
||||
<item>Mediano</item>
|
||||
<item>Grande</item>
|
||||
</string-array>
|
||||
<string name="add_string">Añadir cadena</string>
|
||||
<string name="encryption">Cifrado</string>
|
||||
<string name="key_derivation_function">Función de derivación de clave</string>
|
||||
<string name="beta_dontask">No mostrar nuevamente</string>
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
<string name="accept">Accepter</string>
|
||||
<string name="add_entry">Ajouter une entrée</string>
|
||||
<string name="add_group">Ajouter un groupe</string>
|
||||
<string name="add_string">Ajouter une chaîne</string>
|
||||
<string name="encryption">Chiffrement</string>
|
||||
<string name="encryption_algorithm">Algorithme de chiffrement</string>
|
||||
<string name="key_derivation_function">Fonction de dérivation de clé</string>
|
||||
@@ -154,7 +153,7 @@
|
||||
<string name="rounds_explanation">Des tours de chiffrement supplémentaires fournissent une protection plus élevée contre les attaques par force brute, mais cela peut considérablement ralentir les opérations de chargement et d’enregistrement.</string>
|
||||
<string name="rounds_hint">tours de transformation</string>
|
||||
<string name="memory_usage">Utilisation de la mémoire</string>
|
||||
<string name="memory_usage_explanation">Quantité de mémoire (en multiplets binaires) à utiliser par la fonction de dérivation de clé.</string>
|
||||
<string name="memory_usage_explanation">Quantité de mémoire (en octets) à utiliser par la fonction de dérivation de clé.</string>
|
||||
<string name="parallelism">Parallélisme</string>
|
||||
<string name="parallelism_explanation">Degré de parallélisme (nombre de fils d’exécution) utilisé par la fonction de dérivation de clé.</string>
|
||||
<string name="saving_database">Enregistrement de la base de données…</string>
|
||||
@@ -232,7 +231,7 @@
|
||||
<string name="path">Chemin</string>
|
||||
<string name="assign_master_key">Assigner une clé maîtresse</string>
|
||||
<string name="create_keepass_file">Créer une nouvelle base de données</string>
|
||||
<string name="bytes">Multiplets</string>
|
||||
<string name="bytes">Octets</string>
|
||||
<string name="full_file_path_enable_title">Chemin de fichier</string>
|
||||
<string name="full_file_path_enable_summary">Afficher le chemin complet du fichier</string>
|
||||
<string name="recycle_bin_title">Utiliser la corbeille</string>
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
<string name="accept">Aceptar</string>
|
||||
<string name="add_entry">Engadir entrada</string>
|
||||
<string name="add_group">Engadir grupo</string>
|
||||
<string name="add_string">Engadir texto</string>
|
||||
<string name="encryption">Cifrado</string>
|
||||
<string name="encryption_algorithm">Algoritmo de cifrado</string>
|
||||
<string name="key_derivation_function">Función de derivación de chave</string>
|
||||
|
||||
@@ -184,7 +184,6 @@
|
||||
<item>Nagy</item>
|
||||
</string-array>
|
||||
<string name="edit_entry">Bejegyzés szerkesztése</string>
|
||||
<string name="add_string">Karakterlánc hozzáadása</string>
|
||||
<string name="encryption">Titkosítás</string>
|
||||
<string name="key_derivation_function">Kulcsváltozási függvény</string>
|
||||
<string name="extended_ASCII">Bővített ASCII</string>
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
<string name="accept">Accetto</string>
|
||||
<string name="add_entry">Aggiungi voce</string>
|
||||
<string name="add_group">Aggiungi gruppo</string>
|
||||
<string name="add_string">Aggiungi stringa</string>
|
||||
<string name="encryption_algorithm">Algoritmo di cifratura</string>
|
||||
<string name="app_timeout">Scadenza app</string>
|
||||
<string name="app_timeout_summary">Inattività prima del blocco dell\'app</string>
|
||||
|
||||
@@ -165,7 +165,6 @@
|
||||
<item>גדול</item>
|
||||
</string-array>
|
||||
<string name="edit_entry">ערוך רשומה</string>
|
||||
<string name="add_string">הוסף מחרוזת</string>
|
||||
<string name="encryption">הצפנה</string>
|
||||
<string name="allow">אפשר</string>
|
||||
<string name="clipboard_swipe_clean">החלק לניקוי לוח העתקה עכשיו</string>
|
||||
|
||||
@@ -154,7 +154,6 @@
|
||||
<item>大</item>
|
||||
</string-array>
|
||||
<string name="edit_entry">エントリーを編集</string>
|
||||
<string name="add_string">文字列を追加</string>
|
||||
<string name="encryption">暗号化</string>
|
||||
<string name="key_derivation_function">鍵導出関数</string>
|
||||
<string name="beta_dontask">今後、表示しない</string>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
<string name="add_entry">항목 추가</string>
|
||||
<string name="edit_entry">항목 수정</string>
|
||||
<string name="add_group">그룹 추가</string>
|
||||
<string name="add_string">단어 추가</string>
|
||||
<string name="encryption">암호화</string>
|
||||
<string name="encryption_algorithm">안호화 방식</string>
|
||||
<string name="key_derivation_function">키 파생 기능</string>
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
<string name="accept">Priimti</string>
|
||||
<string name="add_entry">Pridėti įrašą</string>
|
||||
<string name="add_group">Pridėti grupę</string>
|
||||
<string name="add_string">Pridėti eilutę</string>
|
||||
<string name="encryption_algorithm">Algortimas</string>
|
||||
<string name="app_timeout_summary">Laikas, per kurį yra užrakinama duomenų bazė po neveiklumo programėlėje.</string>
|
||||
<string name="application">Programėlė</string>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
<string name="add_entry">Legg til oppføring</string>
|
||||
<string name="edit_entry">Rediger oppføring</string>
|
||||
<string name="add_group">Legg til gruppe</string>
|
||||
<string name="add_string">Legg til streng</string>
|
||||
<string name="encryption">Kryptering</string>
|
||||
<string name="encryption_algorithm">Krypteringsalgoritme</string>
|
||||
<string name="key_derivation_function">Nøkkelutledningsfunksjon</string>
|
||||
|
||||
@@ -161,7 +161,6 @@
|
||||
<item>Groot</item>
|
||||
</string-array>
|
||||
<string name="edit_entry">Item bewerken</string>
|
||||
<string name="add_string">Zin toevoegen</string>
|
||||
<string name="encryption">Versleuteling</string>
|
||||
<string name="key_derivation_function">Sleutelafleidingsfunctie</string>
|
||||
<string name="beta_dontask">Niet meer tonen</string>
|
||||
|
||||
@@ -158,7 +158,6 @@ along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||
<item>Duża</item>
|
||||
</string-array>
|
||||
<string name="edit_entry">Edytuj wpis</string>
|
||||
<string name="add_string">Dodaj ciąg</string>
|
||||
<string name="encryption">Szyfrowanie</string>
|
||||
<string name="key_derivation_function">Funkcja generująca klucz</string>
|
||||
<string name="beta_dontask">Nie pokazuj więcej</string>
|
||||
|
||||
@@ -158,7 +158,6 @@
|
||||
<item>Médio</item>
|
||||
<item>Grande</item>
|
||||
</string-array>
|
||||
<string name="add_string">Adicionar texto</string>
|
||||
<string name="encryption">Encriptação</string>
|
||||
<string name="key_derivation_function">Função de derivação de chave</string>
|
||||
<string name="beta_dontask">Não mostre novamente</string>
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
<string name="accept">Aceitar</string>
|
||||
<string name="add_entry">Adicionar entrada</string>
|
||||
<string name="add_group">Adicionar grupo</string>
|
||||
<string name="add_string">Adicionar linha</string>
|
||||
<string name="encryption_algorithm">Algoritmo de encriptação</string>
|
||||
<string name="app_timeout">Tempo de espera da app</string>
|
||||
<string name="app_timeout_summary">Inatividade antes da app ser bloqueada</string>
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
<string name="accept">Принять</string>
|
||||
<string name="add_entry">Новая запись</string>
|
||||
<string name="add_group">Новая группа</string>
|
||||
<string name="add_string">Новая строка</string>
|
||||
<string name="encryption_algorithm">Алгоритм шифрования</string>
|
||||
<string name="app_timeout">Задержка</string>
|
||||
<string name="app_timeout_summary">Задержка блокировки при бездействии</string>
|
||||
|
||||
@@ -154,7 +154,6 @@
|
||||
<item>Veľké</item>
|
||||
</string-array>
|
||||
<string name="edit_entry">Upraviť záznam</string>
|
||||
<string name="add_string">Pridať reťazec</string>
|
||||
<string name="encryption">Šifrovanie</string>
|
||||
<string name="key_derivation_function">Funkcia pre tvorbu kľúča</string>
|
||||
<string name="beta_dontask">Nezobrazovať znovu</string>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<string name="add_entry">"ఎంట్రీని జత చెయ్యండి "</string>
|
||||
<string name="edit_entry">ఎంట్రీని మార్పు చెయ్యండి</string>
|
||||
<string name="add_group">"గ్రూపుని జత చెయ్యండి "</string>
|
||||
<string name="add_string">"స్ట్రింగ్ ని జత చెయ్యండి "</string>
|
||||
<string name="encryption">ఎన్క్రిప్షన్</string>
|
||||
<string name="encryption_algorithm">ఎన్క్రిప్షన్ అల్గోరిథం</string>
|
||||
<string name="key_derivation_function">కీ వ్యుత్పత్తి ఫంక్షన్</string>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
<string name="add_entry">"Girdi Ekle "</string>
|
||||
<string name="edit_entry">"Girdi Düzenle "</string>
|
||||
<string name="add_group">"Grup Ekle "</string>
|
||||
<string name="add_string">Dizi ekle</string>
|
||||
<string name="encryption">Şifreleme</string>
|
||||
<string name="encryption_algorithm">Şifreleme algoritması</string>
|
||||
<string name="key_derivation_function">Anahtar üretme fonksiyonu</string>
|
||||
@@ -102,7 +101,7 @@
|
||||
<string name="maskpass_summary">Parola maskesi. Varsayılan (***)</string>
|
||||
<string name="menu_about">Hakkında</string>
|
||||
<string name="menu_change_key">Ana anahtarı değitir</string>
|
||||
<string name="copy_field">1$s kopyalandı</string>
|
||||
<string name="copy_field">%1$s kopyalandı</string>
|
||||
<string name="settings">Ayarlar</string>
|
||||
<string name="menu_app_settings">Uygulama ayarları</string>
|
||||
<string name="menu_form_filling_settings">Form doldurma</string>
|
||||
|
||||
@@ -152,7 +152,6 @@
|
||||
<item>中</item>
|
||||
<item>大</item>
|
||||
</string-array>
|
||||
<string name="add_string">添加字符串</string>
|
||||
<string name="encryption">加密</string>
|
||||
<string name="beta_dontask">不再显示</string>
|
||||
<string name="extended_ASCII">ASCⅡ 拓展区字符</string>
|
||||
|
||||
@@ -175,7 +175,6 @@
|
||||
<string name="read_only">唯讀</string>
|
||||
<string name="read_only_warning">KeePass DX 無法存取資料庫所在位置,將以唯讀模式開啟資料庫。</string>
|
||||
<string name="read_only_kitkat_warning">Adnroid 4.4 開始,許多裝置不允許應用程式對 SD 卡進行寫入。</string>
|
||||
<string name="add_string">添加字串</string>
|
||||
<string name="encryption">加密</string>
|
||||
<string name="key_derivation_function">金鑰派生函數</string>
|
||||
<string name="edit_entry">編輯入口</string>
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<color name="colorTextPrimaryInverse">#cccccc</color>
|
||||
<color name="colorText">#616161</color>
|
||||
<color name="colorTextDisable">#c7c7c7</color>
|
||||
<color name="colorTextInverse">#eeeeee</color>
|
||||
<color name="colorTextInverse">#FFFFFF</color>
|
||||
<color name="colorTextInverseDisable">#565656</color>
|
||||
<color name="colorTextSecondary">#7c7c7c</color>
|
||||
<color name="colorTextSecondaryDisable">#c7c7c7</color>
|
||||
|
||||
@@ -132,6 +132,8 @@
|
||||
<string name="setting_icon_pack_choose_key" translatable="false">setting_icon_pack_choose_key</string>
|
||||
<string name="list_entries_show_username_key" translatable="false">list_entries_show_username_key</string>
|
||||
<bool name="list_entries_show_username_default" translatable="false">true</bool>
|
||||
<string name="list_groups_show_number_entries_key" translatable="false">list_groups_show_number_entries_key</string>
|
||||
<bool name="list_groups_show_number_entries_default" translatable="false">true</bool>
|
||||
<string name="list_size_key" translatable="false">list_size</string>
|
||||
<string name="monospace_font_fields_enable_key" translatable="false">monospace_font_extra_fields_enable_key</string>
|
||||
<bool name="monospace_font_fields_enable_default" translatable="false">true</bool>
|
||||
@@ -227,6 +229,7 @@
|
||||
|
||||
<!-- Text Size -->
|
||||
<dimen name="list_icon_size_default" translatable="false">32dp</dimen>
|
||||
<integer name="list_tiny_size_default" translatable="false">9</integer>
|
||||
<integer name="list_small_size_default" translatable="false">13</integer>
|
||||
<string name="list_size_default" translatable="false">16</string>
|
||||
<string-array name="list_size_values">
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
<string name="add_entry">Add entry</string>
|
||||
<string name="edit_entry">Edit entry</string>
|
||||
<string name="add_group">Add group</string>
|
||||
<string name="add_string">Add string</string>
|
||||
<string name="encryption">Encryption</string>
|
||||
<string name="encryption_algorithm">Encryption algorithm</string>
|
||||
<string name="key_derivation_function">Key derivation function</string>
|
||||
@@ -45,6 +44,23 @@
|
||||
<string name="clipboard_timeout">Clipboard timeout</string>
|
||||
<string name="clipboard_timeout_summary">Duration of storage in the clipboard</string>
|
||||
<string name="clipboard_swipe_clean">Swipe to clear clipboard now</string>
|
||||
<string name="content_description_open_file">Open file</string>
|
||||
<string name="content_description_show_file_link">Show file link</string>
|
||||
<string name="content_description_open_file_link">Open file link</string>
|
||||
<string name="content_description_node_children">Node children</string>
|
||||
<string name="content_description_add_node">Add node</string>
|
||||
<string name="content_description_add_entry">Add entry</string>
|
||||
<string name="content_description_add_group">Add group</string>
|
||||
<string name="content_description_file_information">File information</string>
|
||||
<string name="content_description_password_checkbox">Password checkbox</string>
|
||||
<string name="content_description_keyfile_checkbox">Keyfile checkbox</string>
|
||||
<string name="content_description_repeat_toggle_password_visibility">Repeat toggle password visibility</string>
|
||||
<string name="content_description_entry_icon">Entry icon</string>
|
||||
<string name="content_description_entry_save">Entry save</string>
|
||||
<string name="content_description_password_generator">Password generator</string>
|
||||
<string name="content_description_password_length">Password length</string>
|
||||
<string name="content_description_add_field">Add field</string>
|
||||
<string name="content_description_remove_field">Remove field</string>
|
||||
<!--%1$s is either \"Username\" or \"Password\".-->
|
||||
<string name="select_to_copy">Select to copy %1$s to clipboard</string>
|
||||
<string name="retrieving_db_key">Retrieving database key…</string>
|
||||
@@ -113,6 +129,8 @@
|
||||
<string name="length">Length</string>
|
||||
<string name="list_entries_show_username_title">Show usernames</string>
|
||||
<string name="list_entries_show_username_summary">Show usernames in entry lists</string>
|
||||
<string name="list_groups_show_number_entries_title">Show number of entries</string>
|
||||
<string name="list_groups_show_number_entries_summary">Show the number of entries in a group</string>
|
||||
<string name="list_size_title">Size of list items</string>
|
||||
<string name="list_size_summary">Text size in the element list</string>
|
||||
<string name="loading_database">Loading database…</string>
|
||||
@@ -181,7 +199,7 @@
|
||||
<string name="sort_ascending">Lowest first ↓</string>
|
||||
<string name="sort_groups_before">Groups before</string>
|
||||
<string name="sort_recycle_bin_bottom">Recycle bin at the bottom</string>
|
||||
<string name="sort_db">Natural Database</string>
|
||||
<string name="sort_db">Natural order</string>
|
||||
<string name="sort_title">Title</string>
|
||||
<string name="sort_username">Username</string>
|
||||
<string name="sort_creation_time">Creation</string>
|
||||
@@ -329,8 +347,8 @@
|
||||
|
||||
<string name="keyboard_key_sound_title">Sound on keypress</string>
|
||||
|
||||
<string name="allow_no_password_title">Allow no password</string>
|
||||
<string name="allow_no_password_summary">Enable the \"Open\" button if no password identification is selected</string>
|
||||
<string name="allow_no_password_title">Allow no master key</string>
|
||||
<string name="allow_no_password_summary">Enable the \"Open\" button if no credentials are selected</string>
|
||||
<string name="enable_read_only_title">Write-protected</string>
|
||||
<string name="enable_read_only_summary">Open your database read-only by default</string>
|
||||
<string name="delete_entered_password_title">Delete password</string>
|
||||
|
||||
@@ -270,6 +270,12 @@
|
||||
<item name="android:textColor">?attr/colorAccent</item>
|
||||
</style>
|
||||
|
||||
<style name="KeepassDXStyle.TextAppearance.Info" parent="KeepassDXStyle.TextAppearance">
|
||||
<item name="android:textColor">@color/colorTextInverse</item>
|
||||
<item name="android:background">@drawable/background_text_info</item>
|
||||
<item name="backgroundTint">?attr/colorAccent</item>
|
||||
</style>
|
||||
|
||||
<!-- Button Style -->
|
||||
<style name="KeepassDXStyle.v21.Button" parent="Base.TextAppearance.AppCompat.Button">
|
||||
<item name="android:gravity">center</item>
|
||||
|
||||
@@ -44,6 +44,11 @@
|
||||
android:title="@string/list_entries_show_username_title"
|
||||
android:summary="@string/list_entries_show_username_summary"
|
||||
android:defaultValue="@bool/list_entries_show_username_default"/>
|
||||
<SwitchPreference
|
||||
android:key="@string/list_groups_show_number_entries_key"
|
||||
android:title="@string/list_groups_show_number_entries_title"
|
||||
android:summary="@string/list_groups_show_number_entries_summary"
|
||||
android:defaultValue="@bool/list_groups_show_number_entries_default"/>
|
||||
<ListPreference
|
||||
android:key="@string/list_size_key"
|
||||
android:title="@string/list_size_title"
|
||||
|
||||
6
fastlane/metadata/android/en-US/changelogs/21.txt
Normal file
6
fastlane/metadata/android/en-US/changelogs/21.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
* Fix nested groups no longer visible in V1 databases
|
||||
* Improved data import algorithm for V1 databases
|
||||
* Add natural database sort
|
||||
* Add username database sort
|
||||
* Fix button disabled with only KeyFile
|
||||
* Show the number of entries in a group
|
||||
6
fastlane/metadata/android/fr-FR/changelogs/21.txt
Normal file
6
fastlane/metadata/android/fr-FR/changelogs/21.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
* Correction des groupes imbriqués plus visible dans les bases V1
|
||||
* Amélioration de l'algortihme d'import des données pour les bases V1
|
||||
* Ajout du tri par ordre naturel de la base
|
||||
* Ajout du tri par nom d'utilisateur
|
||||
* Correction du bouton désactivé avec seulement un fichier de clé
|
||||
* Affiche le nombre d'entrées dans un groupe
|
||||
Reference in New Issue
Block a user