diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt index 892fa9ca7..dcb9178fe 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt @@ -14,6 +14,7 @@ import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.afollestad.materialdialogs.MaterialDialog +import com.afollestad.materialdialogs.input.input import com.afollestad.materialdialogs.list.listItems import com.elvishew.xlog.XLog 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.widget.AutofitRecyclerView import eu.kanade.tachiyomi.widget.EmptyView +import exh.EXHSavedSearch import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -165,7 +167,94 @@ open class BrowseSourceController(bundle: Bundle) : val newFilters = presenter.source.getFilterList() presenter.sourceFilters = newFilters 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) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterSheet.kt index 4853a058f..24e7580bc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterSheet.kt @@ -3,20 +3,36 @@ package eu.kanade.tachiyomi.ui.browse.source.browse import android.app.Activity import android.content.Context import android.util.AttributeSet +import android.util.TypedValue +import android.view.Gravity +import android.view.View import android.view.ViewGroup +import android.widget.LinearLayout +import android.widget.TextView import com.google.android.material.bottomsheet.BottomSheetDialog import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.items.IFlexible import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.view.inflate 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.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( activity: Activity, onFilterClicked: () -> Unit, - onResetClicked: () -> Unit + onResetClicked: () -> Unit, + // EXH --> + onSaveClicked: () -> Unit, + var onSavedSearchClicked: (Int) -> Unit = {}, + var onSavedSearchDeleteClicked: (Int, String) -> Unit = { index, name -> } + // EXH <-- ) : BottomSheetDialog(activity) { private var filterNavView: FilterNavigationView @@ -29,6 +45,10 @@ class SourceFilterSheet( } filterNavView.onResetClicked = onResetClicked + // EXH --> + filterNavView.onSaveClicked = onSaveClicked + // EXH <-- + setContentView(filterNavView) } @@ -39,6 +59,10 @@ class SourceFilterSheet( class FilterNavigationView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : SimpleNavigationView(context, attrs) { + // EXH --> + var onSaveClicked = {} + // EXH <-- + var onFilterClicked = {} var onResetClicked = {} @@ -52,8 +76,41 @@ class SourceFilterSheet( val view = inflate(R.layout.source_filter_sheet) ((view as ViewGroup).getChildAt(1) as ViewGroup).addView(recycler) addView(view) + save_search_btn.setOnClickListener { onSaveClicked() } filter_btn.setOnClickListener { onFilterClicked() } reset_btn.setOnClickListener { onResetClicked() } } } + + // EXH --> + fun setSavedSearches(searches: List) { + 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 <-- }