Add tags blacklist option for suggestions
parent
6ca9608a80
commit
c92bdae842
@ -0,0 +1,118 @@
|
||||
package org.koitharu.kotatsu.settings.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.EditText
|
||||
import android.widget.Filter
|
||||
import android.widget.MultiAutoCompleteTextView
|
||||
import androidx.annotation.AttrRes
|
||||
import androidx.annotation.MainThread
|
||||
import androidx.annotation.StyleRes
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.preference.EditTextPreference
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.parsers.util.replaceWith
|
||||
|
||||
class MultiAutoCompleteTextViewPreference @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
@AttrRes defStyleAttr: Int = R.attr.multiAutoCompleteTextViewPreferenceStyle,
|
||||
@StyleRes defStyleRes: Int = R.style.Preference_MultiAutoCompleteTextView,
|
||||
) : EditTextPreference(context, attrs, defStyleAttr, defStyleRes) {
|
||||
|
||||
private val autoCompleteBindListener = AutoCompleteBindListener()
|
||||
|
||||
var autoCompleteProvider: AutoCompleteProvider? = null
|
||||
|
||||
init {
|
||||
super.setOnBindEditTextListener(autoCompleteBindListener)
|
||||
}
|
||||
|
||||
override fun setOnBindEditTextListener(onBindEditTextListener: OnBindEditTextListener?) {
|
||||
autoCompleteBindListener.delegate = onBindEditTextListener
|
||||
}
|
||||
|
||||
private inner class AutoCompleteBindListener : OnBindEditTextListener {
|
||||
|
||||
var delegate: OnBindEditTextListener? = null
|
||||
|
||||
override fun onBindEditText(editText: EditText) {
|
||||
delegate?.onBindEditText(editText)
|
||||
if (editText !is MultiAutoCompleteTextView) {
|
||||
return
|
||||
}
|
||||
editText.setTokenizer(MultiAutoCompleteTextView.CommaTokenizer())
|
||||
editText.setAdapter(
|
||||
autoCompleteProvider?.let {
|
||||
CompletionAdapter(editText.context, it, ArrayList())
|
||||
}
|
||||
)
|
||||
editText.threshold = 1
|
||||
}
|
||||
}
|
||||
|
||||
interface AutoCompleteProvider {
|
||||
|
||||
suspend fun getSuggestions(query: String): List<String>
|
||||
}
|
||||
|
||||
class SimpleSummaryProvider(
|
||||
private val emptySummary: CharSequence?,
|
||||
) : SummaryProvider<MultiAutoCompleteTextViewPreference> {
|
||||
|
||||
override fun provideSummary(preference: MultiAutoCompleteTextViewPreference): CharSequence? {
|
||||
return if (preference.text.isNullOrEmpty()) {
|
||||
emptySummary
|
||||
} else {
|
||||
preference.text?.trimEnd(' ', ',')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class CompletionAdapter(
|
||||
context: Context,
|
||||
private val completionProvider: AutoCompleteProvider,
|
||||
private val dataset: MutableList<String>,
|
||||
) : ArrayAdapter<String>(context, android.R.layout.simple_dropdown_item_1line, dataset) {
|
||||
|
||||
override fun getFilter(): Filter {
|
||||
return CompletionFilter(this, completionProvider)
|
||||
}
|
||||
|
||||
fun publishResults(results: List<String>) {
|
||||
dataset.replaceWith(results)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
private class CompletionFilter(
|
||||
private val adapter: CompletionAdapter,
|
||||
private val provider: AutoCompleteProvider,
|
||||
) : Filter() {
|
||||
|
||||
@WorkerThread
|
||||
override fun performFiltering(constraint: CharSequence?): FilterResults {
|
||||
val query = constraint?.toString().orEmpty()
|
||||
val suggestions = runBlocking { provider.getSuggestions(query) }
|
||||
return CompletionResults(suggestions)
|
||||
}
|
||||
|
||||
@MainThread
|
||||
override fun publishResults(constraint: CharSequence?, results: FilterResults) {
|
||||
val completions = (results as CompletionResults).completions
|
||||
adapter.publishResults(completions)
|
||||
}
|
||||
|
||||
private class CompletionResults(
|
||||
val completions: List<String>,
|
||||
) : FilterResults() {
|
||||
|
||||
init {
|
||||
values = completions
|
||||
count = completions.size
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package org.koitharu.kotatsu.settings.utils
|
||||
|
||||
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||
|
||||
class TagsAutoCompleteProvider(
|
||||
private val db: MangaDatabase,
|
||||
) : MultiAutoCompleteTextViewPreference.AutoCompleteProvider {
|
||||
|
||||
override suspend fun getSuggestions(query: String): List<String> {
|
||||
if (query.isEmpty()) {
|
||||
return emptyList()
|
||||
}
|
||||
val tags = db.tagsDao.findTags(query = "$query%", limit = 6)
|
||||
val set = HashSet<String>()
|
||||
val result = ArrayList<String>(tags.size)
|
||||
for (tag in tags) {
|
||||
if (set.add(tag.title)) {
|
||||
result.add(tag.title)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="48dp"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:overScrollMode="ifContentScrolls">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/message"
|
||||
style="?android:attr/textAppearanceSmall"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginLeft="24dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:layout_marginRight="24dp"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:labelFor="@android:id/edit"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
tools:ignore="LabelFor" />
|
||||
|
||||
<MultiAutoCompleteTextView
|
||||
android:id="@android:id/edit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_marginRight="20dp"
|
||||
android:importantForAutofill="no"
|
||||
android:minHeight="48dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
Loading…
Reference in New Issue