Implement logic for saved searches
This commit is contained in:
parent
178cd2b52d
commit
074a1bbca4
@ -14,6 +14,7 @@ import androidx.recyclerview.widget.GridLayoutManager
|
|||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
|
import com.afollestad.materialdialogs.input.input
|
||||||
import com.afollestad.materialdialogs.list.listItems
|
import com.afollestad.materialdialogs.list.listItems
|
||||||
import com.elvishew.xlog.XLog
|
import com.elvishew.xlog.XLog
|
||||||
import com.f2prateek.rx.preferences.Preference
|
import com.f2prateek.rx.preferences.Preference
|
||||||
@ -46,6 +47,7 @@ import eu.kanade.tachiyomi.util.view.snack
|
|||||||
import eu.kanade.tachiyomi.util.view.visible
|
import eu.kanade.tachiyomi.util.view.visible
|
||||||
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
|
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
|
||||||
import eu.kanade.tachiyomi.widget.EmptyView
|
import eu.kanade.tachiyomi.widget.EmptyView
|
||||||
|
import exh.EXHSavedSearch
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
@ -165,7 +167,94 @@ open class BrowseSourceController(bundle: Bundle) :
|
|||||||
val newFilters = presenter.source.getFilterList()
|
val newFilters = presenter.source.getFilterList()
|
||||||
presenter.sourceFilters = newFilters
|
presenter.sourceFilters = newFilters
|
||||||
filterSheet?.setFilters(presenter.filterItems)
|
filterSheet?.setFilters(presenter.filterItems)
|
||||||
|
},
|
||||||
|
onSaveClicked = {
|
||||||
|
filterSheet?.context?.let {
|
||||||
|
MaterialDialog(it)
|
||||||
|
.title(text = "Save current search query?")
|
||||||
|
.input("My search name", hintRes = null) { _, searchName ->
|
||||||
|
val oldSavedSearches = presenter.loadSearches()
|
||||||
|
if (searchName.isNotBlank() &&
|
||||||
|
oldSavedSearches.size < SourceFilterSheet.MAX_SAVED_SEARCHES
|
||||||
|
) {
|
||||||
|
val newSearches = oldSavedSearches + EXHSavedSearch(
|
||||||
|
searchName.toString().trim(),
|
||||||
|
presenter.query,
|
||||||
|
presenter.sourceFilters
|
||||||
|
)
|
||||||
|
presenter.saveSearches(newSearches)
|
||||||
|
filterSheet?.setSavedSearches(newSearches)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.positiveButton(R.string.action_save)
|
||||||
|
.negativeButton(R.string.action_cancel)
|
||||||
|
.cancelable(true)
|
||||||
|
.cancelOnTouchOutside(true)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSavedSearchClicked = cb@{ indexToSearch ->
|
||||||
|
val savedSearches = presenter.loadSearches()
|
||||||
|
|
||||||
|
val search = savedSearches.getOrNull(indexToSearch)
|
||||||
|
|
||||||
|
if (search == null) {
|
||||||
|
filterSheet?.context?.let {
|
||||||
|
MaterialDialog(it)
|
||||||
|
.title(text = "Failed to load saved searches!")
|
||||||
|
.message(text = "An error occurred while loading your saved searches.")
|
||||||
|
.cancelable(true)
|
||||||
|
.cancelOnTouchOutside(true)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
return@cb
|
||||||
|
}
|
||||||
|
|
||||||
|
presenter.sourceFilters = FilterList(search.filterList)
|
||||||
|
filterSheet?.setFilters(presenter.filterItems)
|
||||||
|
val allDefault = presenter.sourceFilters == presenter.source.getFilterList()
|
||||||
|
|
||||||
|
showProgressBar()
|
||||||
|
adapter?.clear()
|
||||||
|
filterSheet?.dismiss()
|
||||||
|
presenter.restartPager(search.query, if (allDefault) FilterList() else presenter.sourceFilters)
|
||||||
|
activity?.invalidateOptionsMenu()
|
||||||
|
},
|
||||||
|
onSavedSearchDeleteClicked = cb@{ indexToDelete, name ->
|
||||||
|
val savedSearches = presenter.loadSearches()
|
||||||
|
|
||||||
|
val search = savedSearches.getOrNull(indexToDelete)
|
||||||
|
|
||||||
|
if (search == null || search.name != name) {
|
||||||
|
filterSheet?.context?.let {
|
||||||
|
MaterialDialog(it)
|
||||||
|
.title(text = "Failed to delete saved search!")
|
||||||
|
.message(text = "An error occurred while deleting the search.")
|
||||||
|
.cancelable(true)
|
||||||
|
.cancelOnTouchOutside(true)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
return@cb
|
||||||
|
}
|
||||||
|
|
||||||
|
filterSheet?.context?.let {
|
||||||
|
MaterialDialog(it)
|
||||||
|
.title(text = "Delete saved search query?")
|
||||||
|
.message(text = "Are you sure you wish to delete your saved search query: '${search.name}'?")
|
||||||
|
.positiveButton(R.string.action_cancel)
|
||||||
|
.negativeButton(text = "Confirm") {
|
||||||
|
val newSearches = savedSearches.filterIndexed { index, _ ->
|
||||||
|
index != indexToDelete
|
||||||
|
}
|
||||||
|
presenter.saveSearches(newSearches)
|
||||||
|
filterSheet!!.setSavedSearches(newSearches)
|
||||||
|
}
|
||||||
|
.cancelable(true)
|
||||||
|
.cancelOnTouchOutside(true)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// EXH <--
|
||||||
)
|
)
|
||||||
filterSheet?.setFilters(presenter.filterItems)
|
filterSheet?.setFilters(presenter.filterItems)
|
||||||
|
|
||||||
|
@ -3,20 +3,36 @@ package eu.kanade.tachiyomi.ui.browse.source.browse
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
|
import android.util.TypedValue
|
||||||
|
import android.view.Gravity
|
||||||
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||||
import eu.kanade.tachiyomi.util.view.inflate
|
import eu.kanade.tachiyomi.util.view.inflate
|
||||||
import eu.kanade.tachiyomi.widget.SimpleNavigationView
|
import eu.kanade.tachiyomi.widget.SimpleNavigationView
|
||||||
|
import exh.EXHSavedSearch
|
||||||
|
import kotlinx.android.synthetic.main.source_filter_sheet.save_search_btn
|
||||||
|
import kotlinx.android.synthetic.main.source_filter_sheet.saved_searches
|
||||||
import kotlinx.android.synthetic.main.source_filter_sheet.view.filter_btn
|
import kotlinx.android.synthetic.main.source_filter_sheet.view.filter_btn
|
||||||
import kotlinx.android.synthetic.main.source_filter_sheet.view.reset_btn
|
import kotlinx.android.synthetic.main.source_filter_sheet.view.reset_btn
|
||||||
|
import kotlinx.android.synthetic.main.source_filter_sheet.view.save_search_btn
|
||||||
|
import kotlinx.android.synthetic.main.source_filter_sheet.view.saved_searches
|
||||||
|
|
||||||
class SourceFilterSheet(
|
class SourceFilterSheet(
|
||||||
activity: Activity,
|
activity: Activity,
|
||||||
onFilterClicked: () -> Unit,
|
onFilterClicked: () -> Unit,
|
||||||
onResetClicked: () -> Unit
|
onResetClicked: () -> Unit,
|
||||||
|
// EXH -->
|
||||||
|
onSaveClicked: () -> Unit,
|
||||||
|
var onSavedSearchClicked: (Int) -> Unit = {},
|
||||||
|
var onSavedSearchDeleteClicked: (Int, String) -> Unit = { index, name -> }
|
||||||
|
// EXH <--
|
||||||
) : BottomSheetDialog(activity) {
|
) : BottomSheetDialog(activity) {
|
||||||
|
|
||||||
private var filterNavView: FilterNavigationView
|
private var filterNavView: FilterNavigationView
|
||||||
@ -29,6 +45,10 @@ class SourceFilterSheet(
|
|||||||
}
|
}
|
||||||
filterNavView.onResetClicked = onResetClicked
|
filterNavView.onResetClicked = onResetClicked
|
||||||
|
|
||||||
|
// EXH -->
|
||||||
|
filterNavView.onSaveClicked = onSaveClicked
|
||||||
|
// EXH <--
|
||||||
|
|
||||||
setContentView(filterNavView)
|
setContentView(filterNavView)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,6 +59,10 @@ class SourceFilterSheet(
|
|||||||
class FilterNavigationView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
class FilterNavigationView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||||
SimpleNavigationView(context, attrs) {
|
SimpleNavigationView(context, attrs) {
|
||||||
|
|
||||||
|
// EXH -->
|
||||||
|
var onSaveClicked = {}
|
||||||
|
// EXH <--
|
||||||
|
|
||||||
var onFilterClicked = {}
|
var onFilterClicked = {}
|
||||||
var onResetClicked = {}
|
var onResetClicked = {}
|
||||||
|
|
||||||
@ -52,8 +76,41 @@ class SourceFilterSheet(
|
|||||||
val view = inflate(R.layout.source_filter_sheet)
|
val view = inflate(R.layout.source_filter_sheet)
|
||||||
((view as ViewGroup).getChildAt(1) as ViewGroup).addView(recycler)
|
((view as ViewGroup).getChildAt(1) as ViewGroup).addView(recycler)
|
||||||
addView(view)
|
addView(view)
|
||||||
|
save_search_btn.setOnClickListener { onSaveClicked() }
|
||||||
filter_btn.setOnClickListener { onFilterClicked() }
|
filter_btn.setOnClickListener { onFilterClicked() }
|
||||||
reset_btn.setOnClickListener { onResetClicked() }
|
reset_btn.setOnClickListener { onResetClicked() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EXH -->
|
||||||
|
fun setSavedSearches(searches: List<EXHSavedSearch>) {
|
||||||
|
saved_searches.removeAllViews()
|
||||||
|
|
||||||
|
val outValue = TypedValue()
|
||||||
|
context.theme.resolveAttribute(android.R.attr.selectableItemBackground, outValue, true)
|
||||||
|
|
||||||
|
save_search_btn.visibility = if (searches.size < MAX_SAVED_SEARCHES) View.VISIBLE else View.GONE
|
||||||
|
|
||||||
|
searches.withIndex().sortedBy { it.value.name }.forEach { (index, search) ->
|
||||||
|
val restoreBtn = TextView(context)
|
||||||
|
restoreBtn.text = search.name
|
||||||
|
val params = LinearLayout.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
params.gravity = Gravity.CENTER
|
||||||
|
restoreBtn.layoutParams = params
|
||||||
|
restoreBtn.gravity = Gravity.CENTER
|
||||||
|
restoreBtn.setBackgroundResource(outValue.resourceId)
|
||||||
|
restoreBtn.setPadding(8.dpToPx, 8.dpToPx, 8.dpToPx, 8.dpToPx)
|
||||||
|
restoreBtn.setOnClickListener { onSavedSearchClicked(index) }
|
||||||
|
restoreBtn.setOnLongClickListener { onSavedSearchDeleteClicked(index, search.name); true }
|
||||||
|
saved_searches.addView(restoreBtn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val MAX_SAVED_SEARCHES = 5
|
||||||
|
}
|
||||||
|
// EXH <--
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user