mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
First commit for autofill blocklist
This commit is contained in:
@@ -307,9 +307,8 @@ class GroupActivity : LockingActivity(),
|
|||||||
val searchInfo: SearchInfo? = intent.getParcelableExtra(KEY_SEARCH_INFO)
|
val searchInfo: SearchInfo? = intent.getParcelableExtra(KEY_SEARCH_INFO)
|
||||||
if (searchInfo != null) {
|
if (searchInfo != null) {
|
||||||
intent.action = Intent.ACTION_SEARCH
|
intent.action = Intent.ACTION_SEARCH
|
||||||
val searchQuery = searchInfo.webDomain ?: searchInfo.applicationId
|
|
||||||
intent.removeExtra(KEY_SEARCH_INFO)
|
intent.removeExtra(KEY_SEARCH_INFO)
|
||||||
intent.putExtra(SearchManager.QUERY, searchQuery)
|
intent.putExtra(SearchManager.QUERY, searchInfo.toString())
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -406,12 +406,9 @@ class Database {
|
|||||||
|
|
||||||
fun createVirtualGroupFromSearch(searchInfo: SearchInfo,
|
fun createVirtualGroupFromSearch(searchInfo: SearchInfo,
|
||||||
max: Int = Integer.MAX_VALUE): Group? {
|
max: Int = Integer.MAX_VALUE): Group? {
|
||||||
val query = (if (searchInfo.webDomain != null)
|
if (searchInfo.isNull())
|
||||||
searchInfo.webDomain
|
return null
|
||||||
else
|
return mSearchHelper?.createVirtualGroupWithSearchResult(this, searchInfo.toString(), SearchParameters().apply {
|
||||||
searchInfo.applicationId)
|
|
||||||
?: return null
|
|
||||||
return mSearchHelper?.createVirtualGroupWithSearchResult(this, query, SearchParameters().apply {
|
|
||||||
searchInTitles = false
|
searchInTitles = false
|
||||||
searchInUserNames = false
|
searchInUserNames = false
|
||||||
searchInPasswords = false
|
searchInPasswords = false
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
package com.kunzisoft.keepass.model
|
package com.kunzisoft.keepass.model
|
||||||
|
|
||||||
|
import android.content.res.Resources
|
||||||
import android.os.Parcel
|
import android.os.Parcel
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
import com.kunzisoft.keepass.utils.ObjectNameResource
|
||||||
|
|
||||||
class SearchInfo : Parcelable {
|
class SearchInfo : ObjectNameResource, Parcelable {
|
||||||
|
|
||||||
var applicationId: String? = null
|
var applicationId: String? = null
|
||||||
var webDomain: String? = null
|
var webDomain: String? = null
|
||||||
|
|
||||||
|
var genericInfo: String? = null
|
||||||
|
|
||||||
constructor()
|
constructor()
|
||||||
|
|
||||||
private constructor(parcel: Parcel) {
|
private constructor(parcel: Parcel) {
|
||||||
@@ -15,6 +19,8 @@ class SearchInfo : Parcelable {
|
|||||||
applicationId = if (readAppId.isNullOrEmpty()) null else readAppId
|
applicationId = if (readAppId.isNullOrEmpty()) null else readAppId
|
||||||
val readDomain = parcel.readString()
|
val readDomain = parcel.readString()
|
||||||
webDomain = if (readDomain.isNullOrEmpty()) null else readDomain
|
webDomain = if (readDomain.isNullOrEmpty()) null else readDomain
|
||||||
|
val readGeneric = parcel.readString()
|
||||||
|
genericInfo = if (readGeneric.isNullOrEmpty()) null else readGeneric
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun describeContents(): Int {
|
override fun describeContents(): Int {
|
||||||
@@ -24,6 +30,39 @@ class SearchInfo : Parcelable {
|
|||||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||||
parcel.writeString(applicationId ?: "")
|
parcel.writeString(applicationId ?: "")
|
||||||
parcel.writeString(webDomain ?: "")
|
parcel.writeString(webDomain ?: "")
|
||||||
|
parcel.writeString(genericInfo ?: "")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName(resources: Resources): String {
|
||||||
|
return applicationId ?: webDomain ?: genericInfo ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isNull(): Boolean {
|
||||||
|
return applicationId == null && webDomain == null && genericInfo == null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as SearchInfo
|
||||||
|
|
||||||
|
if (applicationId != other.applicationId) return false
|
||||||
|
if (webDomain != other.webDomain) return false
|
||||||
|
if (genericInfo != other.genericInfo) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = applicationId?.hashCode() ?: 0
|
||||||
|
result = 31 * result + (webDomain?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (genericInfo?.hashCode() ?: 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return applicationId ?: webDomain ?: genericInfo ?: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -20,9 +20,11 @@
|
|||||||
package com.kunzisoft.keepass.settings
|
package com.kunzisoft.keepass.settings
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
|
|
||||||
import com.kunzisoft.keepass.R
|
import com.kunzisoft.keepass.R
|
||||||
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.AutofillBlacklistPreferenceDialogFragmentCompat
|
||||||
|
|
||||||
class AutofillSettingsFragment : PreferenceFragmentCompat() {
|
class AutofillSettingsFragment : PreferenceFragmentCompat() {
|
||||||
|
|
||||||
@@ -30,4 +32,31 @@ class AutofillSettingsFragment : PreferenceFragmentCompat() {
|
|||||||
// Load the preferences from an XML resource
|
// Load the preferences from an XML resource
|
||||||
setPreferencesFromResource(R.xml.preferences_autofill, rootKey)
|
setPreferencesFromResource(R.xml.preferences_autofill, rootKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDisplayPreferenceDialog(preference: Preference?) {
|
||||||
|
var otherDialogFragment = false
|
||||||
|
|
||||||
|
var dialogFragment: DialogFragment? = null
|
||||||
|
|
||||||
|
when (preference?.key) {
|
||||||
|
getString(R.string.autofill_blocklist_key) -> {
|
||||||
|
dialogFragment = AutofillBlacklistPreferenceDialogFragmentCompat.newInstance(preference.key)
|
||||||
|
}
|
||||||
|
else -> otherDialogFragment = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dialogFragment != null) {
|
||||||
|
dialogFragment.setTargetFragment(this, 0)
|
||||||
|
dialogFragment.show(parentFragmentManager, TAG_AUTOFILL_PREF_FRAGMENT)
|
||||||
|
}
|
||||||
|
// Could not be handled here. Try with the super method.
|
||||||
|
else if (otherDialogFragment) {
|
||||||
|
super.onDisplayPreferenceDialog(preference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private const val TAG_AUTOFILL_PREF_FRAGMENT = "TAG_AUTOFILL_PREF_FRAGMENT"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||||
|
*
|
||||||
|
* This file is part of KeePassDX.
|
||||||
|
*
|
||||||
|
* KeePassDX is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KeePassDX is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.kunzisoft.keepass.settings.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import androidx.preference.DialogPreference
|
||||||
|
import com.kunzisoft.keepass.R
|
||||||
|
import com.kunzisoft.keepass.icons.IconPackChooser
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
open class InputListPreference @JvmOverloads constructor(context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
defStyleAttr: Int = R.attr.dialogPreferenceStyle,
|
||||||
|
defStyleRes: Int = defStyleAttr)
|
||||||
|
: DialogPreference(context, attrs, defStyleAttr, defStyleRes) {
|
||||||
|
|
||||||
|
override fun getDialogLayoutResource(): Int {
|
||||||
|
return R.layout.pref_dialog_input_list
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 Jeremy Jamet / Kunzisoft.
|
||||||
|
*
|
||||||
|
* This file is part of KeePassDX.
|
||||||
|
*
|
||||||
|
* KeePassDX is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KeePassDX is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.kunzisoft.keepass.settings.preferencedialogfragment
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.kunzisoft.keepass.R
|
||||||
|
import com.kunzisoft.keepass.model.SearchInfo
|
||||||
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.adapter.AutofillBlacklistAdapter
|
||||||
|
|
||||||
|
class AutofillBlacklistPreferenceDialogFragmentCompat
|
||||||
|
: InputPreferenceDialogFragmentCompat(),
|
||||||
|
AutofillBlacklistAdapter.ItemDeletedCallback<SearchInfo> {
|
||||||
|
|
||||||
|
private var persistedItems = HashSet<SearchInfo>()
|
||||||
|
|
||||||
|
private var filterAdapter: AutofillBlacklistAdapter<SearchInfo>? = null
|
||||||
|
|
||||||
|
override fun onBindDialogView(view: View) {
|
||||||
|
super.onBindDialogView(view)
|
||||||
|
|
||||||
|
// TODO persistedItems.add
|
||||||
|
|
||||||
|
val addItemButton = view.findViewById<View>(R.id.add_item_button)
|
||||||
|
addItemButton?.setOnClickListener {
|
||||||
|
persistedItems.add(SearchInfo().apply {
|
||||||
|
genericInfo = inputText
|
||||||
|
})
|
||||||
|
filterAdapter?.replaceItems(persistedItems.toList())
|
||||||
|
}
|
||||||
|
|
||||||
|
val recyclerView = view.findViewById<RecyclerView>(R.id.pref_dialog_list)
|
||||||
|
recyclerView.layoutManager = LinearLayoutManager(context)
|
||||||
|
|
||||||
|
activity?.let { activity ->
|
||||||
|
filterAdapter = AutofillBlacklistAdapter(activity)
|
||||||
|
filterAdapter?.setItemDeletedCallback(this)
|
||||||
|
recyclerView.adapter = filterAdapter
|
||||||
|
filterAdapter?.replaceItems(persistedItems.toList())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemDeleted(item: SearchInfo) {
|
||||||
|
persistedItems.remove(item)
|
||||||
|
filterAdapter?.replaceItems(persistedItems.toList())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getStringItems(): Set<String> {
|
||||||
|
val setItems = HashSet<String>()
|
||||||
|
persistedItems.forEach {
|
||||||
|
it.getName(resources).let { item ->
|
||||||
|
setItems.add(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return setItems
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDialogClosed(positiveResult: Boolean) {
|
||||||
|
if (positiveResult) {
|
||||||
|
preference.persistStringSet(getStringItems())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun newInstance(key: String): AutofillBlacklistPreferenceDialogFragmentCompat {
|
||||||
|
val fragment = AutofillBlacklistPreferenceDialogFragmentCompat()
|
||||||
|
val bundle = Bundle(1)
|
||||||
|
bundle.putString(ARG_KEY, key)
|
||||||
|
fragment.arguments = bundle
|
||||||
|
|
||||||
|
return fragment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 Jeremy Jamet / Kunzisoft.
|
||||||
|
*
|
||||||
|
* This file is part of KeePassDX.
|
||||||
|
*
|
||||||
|
* KeePassDX is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KeePassDX is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.kunzisoft.keepass.settings.preferencedialogfragment.adapter
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.TextView
|
||||||
|
|
||||||
|
import com.kunzisoft.keepass.R
|
||||||
|
import com.kunzisoft.keepass.utils.ObjectNameResource
|
||||||
|
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
class AutofillBlacklistAdapter<T : ObjectNameResource>(private val context: Context)
|
||||||
|
: RecyclerView.Adapter<AutofillBlacklistAdapter.BlacklistItemViewHolder>() {
|
||||||
|
|
||||||
|
private val inflater: LayoutInflater = LayoutInflater.from(context)
|
||||||
|
|
||||||
|
val items: MutableList<T> = ArrayList()
|
||||||
|
|
||||||
|
private var itemDeletedCallback: ItemDeletedCallback<T>? = null
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BlacklistItemViewHolder {
|
||||||
|
val view = inflater.inflate(R.layout.pref_dialog_list_removable_item, parent, false)
|
||||||
|
return BlacklistItemViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: BlacklistItemViewHolder, position: Int) {
|
||||||
|
val item = this.items[position]
|
||||||
|
holder.textItem.text = item.getName(context.resources)
|
||||||
|
holder.deleteButton.setOnClickListener(OnItemDeleteClickListener(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int {
|
||||||
|
return items.size
|
||||||
|
}
|
||||||
|
|
||||||
|
fun replaceItems(items: List<T>) {
|
||||||
|
this.items.clear()
|
||||||
|
this.items.addAll(items)
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class OnItemDeleteClickListener(private val itemClicked: T) : View.OnClickListener {
|
||||||
|
|
||||||
|
override fun onClick(view: View) {
|
||||||
|
itemDeletedCallback?.onItemDeleted(itemClicked)
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setItemDeletedCallback(itemDeletedCallback: ItemDeletedCallback<T>) {
|
||||||
|
this.itemDeletedCallback = itemDeletedCallback
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ItemDeletedCallback<T> {
|
||||||
|
fun onItemDeleted(item: T)
|
||||||
|
}
|
||||||
|
|
||||||
|
class BlacklistItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
var textItem: TextView = itemView.findViewById(R.id.pref_dialog_list_text)
|
||||||
|
var deleteButton: ImageView = itemView.findViewById(R.id.pref_dialog_list_delete_button)
|
||||||
|
}
|
||||||
|
}
|
||||||
90
app/src/main/res/layout/pref_dialog_input_list.xml
Normal file
90
app/src/main/res/layout/pref_dialog_input_list.xml
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright 2020 Jeremy Jamet / Kunzisoft.
|
||||||
|
|
||||||
|
This file is part of KeePassDX.
|
||||||
|
|
||||||
|
KeePassDX is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
KeePassDX is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/edit"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:importantForAutofill="noExcludeDescendants"
|
||||||
|
tools:targetApi="o">
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/explanation_text"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
style="@style/KeepassDXStyle.TextAppearance.SmallTitle"/>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.SwitchCompat
|
||||||
|
android:id="@+id/switch_element"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="20dp"
|
||||||
|
android:text="@string/enable"
|
||||||
|
android:background="@drawable/background_button_small"
|
||||||
|
android:textColor="?attr/textColorInverse"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
android:minHeight="48dp"/>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/add_item_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/switch_element"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/input_text"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/add_item_button"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/add_item_button"
|
||||||
|
android:inputType="textUri"
|
||||||
|
android:hint="New item"/>
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/add_item_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:contentDescription="@string/content_description_add_item"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
android:src="@drawable/ic_add_white_24dp" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/pref_dialog_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/add_item_container"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
43
app/src/main/res/layout/pref_dialog_list_removable_item.xml
Normal file
43
app/src/main/res/layout/pref_dialog_list_removable_item.xml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||||
|
|
||||||
|
This file is part of KeePassDX.
|
||||||
|
|
||||||
|
KeePassDX is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
KeePassDX is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/pref_dialog_list_container"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp">
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/pref_dialog_list_text"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/pref_dialog_list_delete_button"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/pref_dialog_list_delete_button"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/pref_dialog_list_delete_button"/>
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/pref_dialog_list_delete_button"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
android:src="@drawable/ic_content_delete_white_24dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -132,6 +132,7 @@
|
|||||||
<bool name="keyboard_key_sound_default" translatable="false">false</bool>
|
<bool name="keyboard_key_sound_default" translatable="false">false</bool>
|
||||||
<string name="autofill_auto_search_key" translatable="false">autofill_auto_search_key</string>
|
<string name="autofill_auto_search_key" translatable="false">autofill_auto_search_key</string>
|
||||||
<bool name="autofill_auto_search_default" translatable="false">true</bool>
|
<bool name="autofill_auto_search_default" translatable="false">true</bool>
|
||||||
|
<string name="autofill_blocklist_key" translatable="false">autofill_blocklist_key</string>
|
||||||
|
|
||||||
<!-- Advanced Unlock Settings -->
|
<!-- Advanced Unlock Settings -->
|
||||||
<string name="settings_advanced_unlock_key" translatable="false">settings_advanced_unlock_key</string>
|
<string name="settings_advanced_unlock_key" translatable="false">settings_advanced_unlock_key</string>
|
||||||
|
|||||||
@@ -52,6 +52,7 @@
|
|||||||
<string name="content_description_add_node">Add node</string>
|
<string name="content_description_add_node">Add node</string>
|
||||||
<string name="content_description_add_entry">Add entry</string>
|
<string name="content_description_add_entry">Add entry</string>
|
||||||
<string name="content_description_add_group">Add group</string>
|
<string name="content_description_add_group">Add group</string>
|
||||||
|
<string name="content_description_add_item">Add item</string>
|
||||||
<string name="content_description_file_information">File information</string>
|
<string name="content_description_file_information">File information</string>
|
||||||
<string name="content_description_password_checkbox">Password checkbox</string>
|
<string name="content_description_password_checkbox">Password checkbox</string>
|
||||||
<string name="content_description_keyfile_checkbox">Keyfile checkbox</string>
|
<string name="content_description_keyfile_checkbox">Keyfile checkbox</string>
|
||||||
@@ -230,6 +231,7 @@
|
|||||||
<string name="do_not_kill_app">Do not kill the app…</string>
|
<string name="do_not_kill_app">Do not kill the app…</string>
|
||||||
<string name="space">Space</string>
|
<string name="space">Space</string>
|
||||||
<string name="search_label">Search</string>
|
<string name="search_label">Search</string>
|
||||||
|
<string name="filter">Filter</string>
|
||||||
<string name="sort_menu">Sort</string>
|
<string name="sort_menu">Sort</string>
|
||||||
<string name="sort_ascending">Lowest first ↓</string>
|
<string name="sort_ascending">Lowest first ↓</string>
|
||||||
<string name="sort_groups_before">Groups before</string>
|
<string name="sort_groups_before">Groups before</string>
|
||||||
@@ -379,6 +381,7 @@
|
|||||||
<string name="keyboard_key_sound_title">Audible keypresses</string>
|
<string name="keyboard_key_sound_title">Audible keypresses</string>
|
||||||
<string name="autofill_auto_search_title">Auto search</string>
|
<string name="autofill_auto_search_title">Auto search</string>
|
||||||
<string name="autofill_auto_search_summary">Automatically suggest search results from the web domain or application Id</string>
|
<string name="autofill_auto_search_summary">Automatically suggest search results from the web domain or application Id</string>
|
||||||
|
<string name="autofill_blocklist_title">Blacklist</string>
|
||||||
<string name="allow_no_password_title">Allow no master key</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="allow_no_password_summary">Enable the \"Open\" button if no credentials are selected</string>
|
||||||
<string name="delete_entered_password_title">Delete password</string>
|
<string name="delete_entered_password_title">Delete password</string>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
Copyright 2018 Jeremy Jamet / Kunzisoft.
|
Copyright 2020 Jeremy Jamet / Kunzisoft.
|
||||||
|
|
||||||
This file is part of KeePassDX.
|
This file is part of KeePassDX.
|
||||||
|
|
||||||
@@ -26,4 +26,10 @@
|
|||||||
android:summary="@string/autofill_auto_search_summary"
|
android:summary="@string/autofill_auto_search_summary"
|
||||||
android:defaultValue="@bool/autofill_auto_search_default"/>
|
android:defaultValue="@bool/autofill_auto_search_default"/>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
<PreferenceCategory
|
||||||
|
android:title="@string/filter">
|
||||||
|
<com.kunzisoft.keepass.settings.preference.InputListPreference
|
||||||
|
android:key="@string/autofill_blocklist_key"
|
||||||
|
android:title="@string/autofill_blocklist_title"/>
|
||||||
|
</PreferenceCategory>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
Reference in New Issue
Block a user