|
|
|
|
@ -1,20 +1,32 @@
|
|
|
|
|
package org.koitharu.kotatsu.filter.ui.sheet
|
|
|
|
|
|
|
|
|
|
import android.os.Bundle
|
|
|
|
|
import android.text.InputFilter
|
|
|
|
|
import android.view.LayoutInflater
|
|
|
|
|
import android.view.View
|
|
|
|
|
import android.view.ViewGroup
|
|
|
|
|
import android.view.inputmethod.EditorInfo
|
|
|
|
|
import android.widget.AdapterView
|
|
|
|
|
import android.widget.ArrayAdapter
|
|
|
|
|
import androidx.appcompat.widget.PopupMenu
|
|
|
|
|
import androidx.core.view.WindowInsetsCompat
|
|
|
|
|
import androidx.core.view.isGone
|
|
|
|
|
import androidx.core.view.updateLayoutParams
|
|
|
|
|
import androidx.core.view.updatePadding
|
|
|
|
|
import com.google.android.material.chip.Chip
|
|
|
|
|
import com.google.android.material.slider.RangeSlider
|
|
|
|
|
import com.google.android.material.slider.Slider
|
|
|
|
|
import com.google.android.material.snackbar.Snackbar
|
|
|
|
|
import kotlinx.coroutines.Dispatchers
|
|
|
|
|
import kotlinx.coroutines.flow.combine
|
|
|
|
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
|
|
|
|
import kotlinx.coroutines.flow.flowOn
|
|
|
|
|
import kotlinx.coroutines.flow.map
|
|
|
|
|
import org.koitharu.kotatsu.R
|
|
|
|
|
import org.koitharu.kotatsu.core.model.titleResId
|
|
|
|
|
import org.koitharu.kotatsu.core.nav.router
|
|
|
|
|
import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
|
|
|
|
|
import org.koitharu.kotatsu.core.ui.dialog.setEditText
|
|
|
|
|
import org.koitharu.kotatsu.core.ui.model.titleRes
|
|
|
|
|
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
|
|
|
|
|
import org.koitharu.kotatsu.core.ui.widgets.ChipsView
|
|
|
|
|
@ -26,8 +38,9 @@ import org.koitharu.kotatsu.core.util.ext.parentView
|
|
|
|
|
import org.koitharu.kotatsu.core.util.ext.setValueRounded
|
|
|
|
|
import org.koitharu.kotatsu.core.util.ext.setValuesRounded
|
|
|
|
|
import org.koitharu.kotatsu.databinding.SheetFilterBinding
|
|
|
|
|
import org.koitharu.kotatsu.filter.data.PersistableFilter
|
|
|
|
|
import org.koitharu.kotatsu.filter.data.PersistableFilter.Companion.MAX_TITLE_LENGTH
|
|
|
|
|
import org.koitharu.kotatsu.filter.ui.FilterCoordinator
|
|
|
|
|
import org.koitharu.kotatsu.filter.data.SavedFiltersRepository
|
|
|
|
|
import org.koitharu.kotatsu.filter.ui.model.FilterProperty
|
|
|
|
|
import org.koitharu.kotatsu.parsers.model.ContentRating
|
|
|
|
|
import org.koitharu.kotatsu.parsers.model.ContentType
|
|
|
|
|
@ -38,417 +51,451 @@ import org.koitharu.kotatsu.parsers.model.SortOrder
|
|
|
|
|
import org.koitharu.kotatsu.parsers.model.YEAR_UNKNOWN
|
|
|
|
|
import org.koitharu.kotatsu.parsers.util.toIntUp
|
|
|
|
|
import java.util.Locale
|
|
|
|
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
|
|
|
import android.widget.EditText
|
|
|
|
|
|
|
|
|
|
class FilterSheetFragment : BaseAdaptiveSheet<SheetFilterBinding>(),
|
|
|
|
|
AdapterView.OnItemSelectedListener,
|
|
|
|
|
ChipsView.OnChipClickListener {
|
|
|
|
|
AdapterView.OnItemSelectedListener,
|
|
|
|
|
View.OnClickListener,
|
|
|
|
|
ChipsView.OnChipClickListener,
|
|
|
|
|
ChipsView.OnChipLongClickListener,
|
|
|
|
|
ChipsView.OnChipCloseClickListener {
|
|
|
|
|
|
|
|
|
|
override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): SheetFilterBinding {
|
|
|
|
|
return SheetFilterBinding.inflate(inflater, container, false)
|
|
|
|
|
}
|
|
|
|
|
override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): SheetFilterBinding {
|
|
|
|
|
return SheetFilterBinding.inflate(inflater, container, false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun onSavedPresetsChanged(list: List<SavedFiltersRepository.Preset>, selectedId: Long?) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
if (list.isEmpty()) {
|
|
|
|
|
b.layoutSavedFilters.isGone = true
|
|
|
|
|
b.chipsSavedFilters.setChips(emptyList())
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
b.layoutSavedFilters.isGone = false
|
|
|
|
|
val chips = list.map { p ->
|
|
|
|
|
ChipsView.ChipModel(
|
|
|
|
|
title = p.name,
|
|
|
|
|
isChecked = p.id == selectedId,
|
|
|
|
|
data = p,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
b.chipsSavedFilters.setChips(chips)
|
|
|
|
|
}
|
|
|
|
|
override fun onViewBindingCreated(binding: SheetFilterBinding, savedInstanceState: Bundle?) {
|
|
|
|
|
super.onViewBindingCreated(binding, savedInstanceState)
|
|
|
|
|
if (dialog == null) {
|
|
|
|
|
binding.layoutBody.updatePadding(top = binding.layoutBody.paddingBottom)
|
|
|
|
|
binding.scrollView.scrollIndicators = 0
|
|
|
|
|
}
|
|
|
|
|
val filter = FilterCoordinator.require(this)
|
|
|
|
|
filter.sortOrder.observe(viewLifecycleOwner, this::onSortOrderChanged)
|
|
|
|
|
filter.locale.observe(viewLifecycleOwner, this::onLocaleChanged)
|
|
|
|
|
filter.originalLocale.observe(viewLifecycleOwner, this::onOriginalLocaleChanged)
|
|
|
|
|
filter.tags.observe(viewLifecycleOwner, this::onTagsChanged)
|
|
|
|
|
filter.tagsExcluded.observe(viewLifecycleOwner, this::onTagsExcludedChanged)
|
|
|
|
|
filter.states.observe(viewLifecycleOwner, this::onStateChanged)
|
|
|
|
|
filter.contentTypes.observe(viewLifecycleOwner, this::onContentTypesChanged)
|
|
|
|
|
filter.contentRating.observe(viewLifecycleOwner, this::onContentRatingChanged)
|
|
|
|
|
filter.demographics.observe(viewLifecycleOwner, this::onDemographicsChanged)
|
|
|
|
|
filter.year.observe(viewLifecycleOwner, this::onYearChanged)
|
|
|
|
|
filter.yearRange.observe(viewLifecycleOwner, this::onYearRangeChanged)
|
|
|
|
|
filter.savedFilters.observe(viewLifecycleOwner, ::onSavedPresetsChanged)
|
|
|
|
|
|
|
|
|
|
private fun promptPresetName(onSubmit: (String) -> Unit) {
|
|
|
|
|
val ctx = requireContext()
|
|
|
|
|
val input = EditText(ctx)
|
|
|
|
|
MaterialAlertDialogBuilder(ctx)
|
|
|
|
|
.setTitle(R.string.enter_name)
|
|
|
|
|
.setView(input)
|
|
|
|
|
.setPositiveButton(R.string.save) { d, _ ->
|
|
|
|
|
val text = input.text?.toString()?.trim()
|
|
|
|
|
if (!text.isNullOrEmpty()) onSubmit(text)
|
|
|
|
|
d.dismiss()
|
|
|
|
|
}
|
|
|
|
|
.setNegativeButton(android.R.string.cancel) { d, _ -> d.dismiss() }
|
|
|
|
|
.show()
|
|
|
|
|
}
|
|
|
|
|
binding.layoutGenres.setTitle(
|
|
|
|
|
if (filter.capabilities.isMultipleTagsSupported) {
|
|
|
|
|
R.string.genres
|
|
|
|
|
} else {
|
|
|
|
|
R.string.genre
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
binding.spinnerLocale.onItemSelectedListener = this
|
|
|
|
|
binding.spinnerOriginalLocale.onItemSelectedListener = this
|
|
|
|
|
binding.spinnerOrder.onItemSelectedListener = this
|
|
|
|
|
binding.chipsSavedFilters.onChipClickListener = this
|
|
|
|
|
binding.chipsState.onChipClickListener = this
|
|
|
|
|
binding.chipsTypes.onChipClickListener = this
|
|
|
|
|
binding.chipsContentRating.onChipClickListener = this
|
|
|
|
|
binding.chipsDemographics.onChipClickListener = this
|
|
|
|
|
binding.chipsGenres.onChipClickListener = this
|
|
|
|
|
binding.chipsGenresExclude.onChipClickListener = this
|
|
|
|
|
binding.chipsSavedFilters.onChipLongClickListener = this
|
|
|
|
|
binding.chipsSavedFilters.onChipCloseClickListener = this
|
|
|
|
|
binding.sliderYear.addOnChangeListener(this::onSliderValueChange)
|
|
|
|
|
binding.sliderYearsRange.addOnChangeListener(this::onRangeSliderValueChange)
|
|
|
|
|
binding.layoutGenres.setOnMoreButtonClickListener {
|
|
|
|
|
router.showTagsCatalogSheet(excludeMode = false)
|
|
|
|
|
}
|
|
|
|
|
binding.layoutGenresExclude.setOnMoreButtonClickListener {
|
|
|
|
|
router.showTagsCatalogSheet(excludeMode = true)
|
|
|
|
|
}
|
|
|
|
|
filter.observe().observe(viewLifecycleOwner) {
|
|
|
|
|
binding.buttonReset.isEnabled = it.listFilter.isNotEmpty()
|
|
|
|
|
}
|
|
|
|
|
combine(
|
|
|
|
|
filter.observe().map { it.listFilter.isNotEmpty() }.distinctUntilChanged(),
|
|
|
|
|
filter.savedFilters.map { it.selectedItems.isEmpty() }.distinctUntilChanged(),
|
|
|
|
|
Boolean::and,
|
|
|
|
|
).flowOn(Dispatchers.Default)
|
|
|
|
|
.observe(viewLifecycleOwner) {
|
|
|
|
|
binding.buttonSave.isEnabled = it
|
|
|
|
|
}
|
|
|
|
|
binding.buttonSave.setOnClickListener(this)
|
|
|
|
|
binding.buttonReset.setOnClickListener(this)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun showPresetOptions(filter: FilterCoordinator, preset: SavedFiltersRepository.Preset) {
|
|
|
|
|
val ctx = requireContext()
|
|
|
|
|
val items = arrayOf(getString(R.string.edit), getString(R.string.delete))
|
|
|
|
|
MaterialAlertDialogBuilder(ctx)
|
|
|
|
|
.setItems(items) { d, which ->
|
|
|
|
|
when (which) {
|
|
|
|
|
0 -> promptRename(filter, preset)
|
|
|
|
|
1 -> filter.deletePreset(preset.id)
|
|
|
|
|
}
|
|
|
|
|
d.dismiss()
|
|
|
|
|
}
|
|
|
|
|
.show()
|
|
|
|
|
}
|
|
|
|
|
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
|
|
|
|
|
val typeMask = WindowInsetsCompat.Type.systemBars()
|
|
|
|
|
viewBinding?.layoutBottom?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
|
|
|
|
bottomMargin = insets.getInsets(typeMask).bottom
|
|
|
|
|
}
|
|
|
|
|
return insets.consume(v, typeMask, bottom = true)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun promptRename(filter: FilterCoordinator, preset: SavedFiltersRepository.Preset) {
|
|
|
|
|
val ctx = requireContext()
|
|
|
|
|
val input = EditText(ctx)
|
|
|
|
|
input.setText(preset.name)
|
|
|
|
|
MaterialAlertDialogBuilder(ctx)
|
|
|
|
|
.setTitle(R.string.edit)
|
|
|
|
|
.setView(input)
|
|
|
|
|
.setPositiveButton(R.string.save) { d, _ ->
|
|
|
|
|
val text = input.text?.toString()?.trim()
|
|
|
|
|
if (!text.isNullOrEmpty()) filter.renamePreset(preset.id, text)
|
|
|
|
|
d.dismiss()
|
|
|
|
|
}
|
|
|
|
|
.setNegativeButton(android.R.string.cancel) { d, _ -> d.dismiss() }
|
|
|
|
|
.show()
|
|
|
|
|
}
|
|
|
|
|
override fun onClick(v: View) {
|
|
|
|
|
when (v.id) {
|
|
|
|
|
R.id.button_reset -> FilterCoordinator.require(this).reset()
|
|
|
|
|
R.id.button_save -> onSaveFilterClick()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun onViewBindingCreated(binding: SheetFilterBinding, savedInstanceState: Bundle?) {
|
|
|
|
|
super.onViewBindingCreated(binding, savedInstanceState)
|
|
|
|
|
if (dialog == null) {
|
|
|
|
|
binding.layoutBody.updatePadding(top = binding.layoutBody.paddingBottom)
|
|
|
|
|
binding.scrollView.scrollIndicators = 0
|
|
|
|
|
}
|
|
|
|
|
val filter = FilterCoordinator.require(this)
|
|
|
|
|
filter.sortOrder.observe(viewLifecycleOwner, this::onSortOrderChanged)
|
|
|
|
|
filter.locale.observe(viewLifecycleOwner, this::onLocaleChanged)
|
|
|
|
|
filter.originalLocale.observe(viewLifecycleOwner, this::onOriginalLocaleChanged)
|
|
|
|
|
filter.tags.observe(viewLifecycleOwner, this::onTagsChanged)
|
|
|
|
|
filter.tagsExcluded.observe(viewLifecycleOwner, this::onTagsExcludedChanged)
|
|
|
|
|
filter.states.observe(viewLifecycleOwner, this::onStateChanged)
|
|
|
|
|
filter.contentTypes.observe(viewLifecycleOwner, this::onContentTypesChanged)
|
|
|
|
|
filter.contentRating.observe(viewLifecycleOwner, this::onContentRatingChanged)
|
|
|
|
|
filter.demographics.observe(viewLifecycleOwner, this::onDemographicsChanged)
|
|
|
|
|
filter.year.observe(viewLifecycleOwner, this::onYearChanged)
|
|
|
|
|
filter.yearRange.observe(viewLifecycleOwner, this::onYearRangeChanged)
|
|
|
|
|
override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
|
|
|
|
|
val filter = FilterCoordinator.require(this)
|
|
|
|
|
when (parent.id) {
|
|
|
|
|
R.id.spinner_order -> filter.setSortOrder(filter.sortOrder.value.availableItems[position])
|
|
|
|
|
R.id.spinner_locale -> filter.setLocale(filter.locale.value.availableItems[position])
|
|
|
|
|
R.id.spinner_original_locale -> filter.setOriginalLocale(filter.originalLocale.value.availableItems[position])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
binding.layoutGenres.setTitle(
|
|
|
|
|
if (filter.capabilities.isMultipleTagsSupported) {
|
|
|
|
|
R.string.genres
|
|
|
|
|
} else {
|
|
|
|
|
R.string.genre
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
binding.spinnerLocale.onItemSelectedListener = this
|
|
|
|
|
binding.spinnerOriginalLocale.onItemSelectedListener = this
|
|
|
|
|
binding.spinnerOrder.onItemSelectedListener = this
|
|
|
|
|
binding.chipsState.onChipClickListener = this
|
|
|
|
|
binding.chipsTypes.onChipClickListener = this
|
|
|
|
|
binding.chipsContentRating.onChipClickListener = this
|
|
|
|
|
binding.chipsDemographics.onChipClickListener = this
|
|
|
|
|
binding.chipsGenres.onChipClickListener = this
|
|
|
|
|
binding.chipsGenresExclude.onChipClickListener = this
|
|
|
|
|
binding.sliderYear.addOnChangeListener(this::onSliderValueChange)
|
|
|
|
|
binding.sliderYearsRange.addOnChangeListener(this::onRangeSliderValueChange)
|
|
|
|
|
binding.layoutGenres.setOnMoreButtonClickListener {
|
|
|
|
|
router.showTagsCatalogSheet(excludeMode = false)
|
|
|
|
|
}
|
|
|
|
|
binding.layoutGenresExclude.setOnMoreButtonClickListener {
|
|
|
|
|
router.showTagsCatalogSheet(excludeMode = true)
|
|
|
|
|
}
|
|
|
|
|
override fun onNothingSelected(parent: AdapterView<*>?) = Unit
|
|
|
|
|
|
|
|
|
|
binding.chipsSavedFilters.onChipClickListener = ChipsView.OnChipClickListener { chip, data ->
|
|
|
|
|
when (data) {
|
|
|
|
|
is SavedFiltersRepository.Preset -> filter.applyPreset(data)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
binding.chipsSavedFilters.onChipLongClickListener = ChipsView.OnChipLongClickListener { chip, data ->
|
|
|
|
|
when (data) {
|
|
|
|
|
is SavedFiltersRepository.Preset -> {
|
|
|
|
|
showPresetOptions(filter, data)
|
|
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
else -> false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private fun onSliderValueChange(slider: Slider, value: Float, fromUser: Boolean) {
|
|
|
|
|
if (!fromUser) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val intValue = value.toInt()
|
|
|
|
|
val filter = FilterCoordinator.require(this)
|
|
|
|
|
when (slider.id) {
|
|
|
|
|
R.id.slider_year -> filter.setYear(
|
|
|
|
|
if (intValue <= slider.valueFrom.toIntUp()) {
|
|
|
|
|
YEAR_UNKNOWN
|
|
|
|
|
} else {
|
|
|
|
|
intValue
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
filter.savedPresets.observe(viewLifecycleOwner) { list ->
|
|
|
|
|
val selectedId = filter.selectedPresetId.value
|
|
|
|
|
onSavedPresetsChanged(list, selectedId)
|
|
|
|
|
}
|
|
|
|
|
filter.selectedPresetId.observe(viewLifecycleOwner) { selectedId ->
|
|
|
|
|
onSavedPresetsChanged(filter.savedPresets.value, selectedId)
|
|
|
|
|
}
|
|
|
|
|
private fun onRangeSliderValueChange(slider: RangeSlider, value: Float, fromUser: Boolean) {
|
|
|
|
|
if (!fromUser) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val filter = FilterCoordinator.require(this)
|
|
|
|
|
when (slider.id) {
|
|
|
|
|
R.id.slider_yearsRange -> filter.setYearRange(
|
|
|
|
|
valueFrom = slider.values.firstOrNull()?.let {
|
|
|
|
|
if (it <= slider.valueFrom) YEAR_UNKNOWN else it.toInt()
|
|
|
|
|
} ?: YEAR_UNKNOWN,
|
|
|
|
|
valueTo = slider.values.lastOrNull()?.let {
|
|
|
|
|
if (it >= slider.valueTo) YEAR_UNKNOWN else it.toInt()
|
|
|
|
|
} ?: YEAR_UNKNOWN,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
filter.observe().observe(viewLifecycleOwner) {
|
|
|
|
|
binding.buttonSaveFilter.isEnabled = filter.isFilterApplied
|
|
|
|
|
}
|
|
|
|
|
binding.buttonSaveFilter.setOnClickListener {
|
|
|
|
|
promptPresetName { name ->
|
|
|
|
|
filter.saveCurrentPreset(name)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
override fun onChipClick(chip: Chip, data: Any?) {
|
|
|
|
|
val filter = FilterCoordinator.require(this)
|
|
|
|
|
when (data) {
|
|
|
|
|
is MangaState -> filter.toggleState(data, !chip.isChecked)
|
|
|
|
|
is MangaTag -> if (chip.parentView?.id == R.id.chips_genresExclude) {
|
|
|
|
|
filter.toggleTagExclude(data, !chip.isChecked)
|
|
|
|
|
} else {
|
|
|
|
|
filter.toggleTag(data, !chip.isChecked)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
|
|
|
|
|
val typeMask = WindowInsetsCompat.Type.systemBars()
|
|
|
|
|
viewBinding?.scrollView?.updatePadding(
|
|
|
|
|
bottom = insets.getInsets(typeMask).bottom,
|
|
|
|
|
)
|
|
|
|
|
return insets.consume(v, typeMask, bottom = true)
|
|
|
|
|
}
|
|
|
|
|
is ContentType -> filter.toggleContentType(data, !chip.isChecked)
|
|
|
|
|
is ContentRating -> filter.toggleContentRating(data, !chip.isChecked)
|
|
|
|
|
is Demographic -> filter.toggleDemographic(data, !chip.isChecked)
|
|
|
|
|
is PersistableFilter -> filter.setAdjusted(data.filter)
|
|
|
|
|
null -> router.showTagsCatalogSheet(excludeMode = chip.parentView?.id == R.id.chips_genresExclude)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
|
|
|
|
|
val filter = FilterCoordinator.require(this)
|
|
|
|
|
when (parent.id) {
|
|
|
|
|
R.id.spinner_order -> filter.setSortOrder(filter.sortOrder.value.availableItems[position])
|
|
|
|
|
R.id.spinner_locale -> filter.setLocale(filter.locale.value.availableItems[position])
|
|
|
|
|
R.id.spinner_original_locale -> filter.setOriginalLocale(filter.originalLocale.value.availableItems[position])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
override fun onChipLongClick(chip: Chip, data: Any?): Boolean {
|
|
|
|
|
return when (data) {
|
|
|
|
|
is PersistableFilter -> {
|
|
|
|
|
showSavedFilterMenu(chip, data)
|
|
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun onNothingSelected(parent: AdapterView<*>?) = Unit
|
|
|
|
|
else -> false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun onSliderValueChange(slider: Slider, value: Float, fromUser: Boolean) {
|
|
|
|
|
if (!fromUser) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val intValue = value.toInt()
|
|
|
|
|
val filter = FilterCoordinator.require(this)
|
|
|
|
|
when (slider.id) {
|
|
|
|
|
R.id.slider_year -> filter.setYear(
|
|
|
|
|
if (intValue <= slider.valueFrom.toIntUp()) {
|
|
|
|
|
YEAR_UNKNOWN
|
|
|
|
|
} else {
|
|
|
|
|
intValue
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
override fun onChipCloseClick(chip: Chip, data: Any?) {
|
|
|
|
|
when (data) {
|
|
|
|
|
is PersistableFilter -> {
|
|
|
|
|
showSavedFilterMenu(chip, data)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun onRangeSliderValueChange(slider: RangeSlider, value: Float, fromUser: Boolean) {
|
|
|
|
|
if (!fromUser) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val filter = FilterCoordinator.require(this)
|
|
|
|
|
when (slider.id) {
|
|
|
|
|
R.id.slider_yearsRange -> filter.setYearRange(
|
|
|
|
|
valueFrom = slider.values.firstOrNull()?.let {
|
|
|
|
|
if (it <= slider.valueFrom) YEAR_UNKNOWN else it.toInt()
|
|
|
|
|
} ?: YEAR_UNKNOWN,
|
|
|
|
|
valueTo = slider.values.lastOrNull()?.let {
|
|
|
|
|
if (it >= slider.valueTo) YEAR_UNKNOWN else it.toInt()
|
|
|
|
|
} ?: YEAR_UNKNOWN,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private fun onSortOrderChanged(value: FilterProperty<SortOrder>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutOrder.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val selected = value.selectedItems.single()
|
|
|
|
|
b.spinnerOrder.adapter = ArrayAdapter(
|
|
|
|
|
b.spinnerOrder.context,
|
|
|
|
|
android.R.layout.simple_spinner_dropdown_item,
|
|
|
|
|
android.R.id.text1,
|
|
|
|
|
value.availableItems.map { b.spinnerOrder.context.getString(it.titleRes) },
|
|
|
|
|
)
|
|
|
|
|
val selectedIndex = value.availableItems.indexOf(selected)
|
|
|
|
|
if (selectedIndex >= 0) {
|
|
|
|
|
b.spinnerOrder.setSelection(selectedIndex, false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun onChipClick(chip: Chip, data: Any?) {
|
|
|
|
|
val filter = FilterCoordinator.require(this)
|
|
|
|
|
when (data) {
|
|
|
|
|
is MangaState -> filter.toggleState(data, !chip.isChecked)
|
|
|
|
|
is MangaTag -> if (chip.parentView?.id == R.id.chips_genresExclude) {
|
|
|
|
|
filter.toggleTagExclude(data, !chip.isChecked)
|
|
|
|
|
} else {
|
|
|
|
|
filter.toggleTag(data, !chip.isChecked)
|
|
|
|
|
}
|
|
|
|
|
private fun onLocaleChanged(value: FilterProperty<Locale?>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutLocale.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val selected = value.selectedItems.singleOrNull()
|
|
|
|
|
b.spinnerLocale.adapter = ArrayAdapter(
|
|
|
|
|
b.spinnerLocale.context,
|
|
|
|
|
android.R.layout.simple_spinner_dropdown_item,
|
|
|
|
|
android.R.id.text1,
|
|
|
|
|
value.availableItems.map { it.getDisplayName(b.spinnerLocale.context) },
|
|
|
|
|
)
|
|
|
|
|
val selectedIndex = value.availableItems.indexOf(selected)
|
|
|
|
|
if (selectedIndex >= 0) {
|
|
|
|
|
b.spinnerLocale.setSelection(selectedIndex, false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
is ContentType -> filter.toggleContentType(data, !chip.isChecked)
|
|
|
|
|
is ContentRating -> filter.toggleContentRating(data, !chip.isChecked)
|
|
|
|
|
is Demographic -> filter.toggleDemographic(data, !chip.isChecked)
|
|
|
|
|
null -> router.showTagsCatalogSheet(excludeMode = chip.parentView?.id == R.id.chips_genresExclude)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private fun onOriginalLocaleChanged(value: FilterProperty<Locale?>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutOriginalLocale.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val selected = value.selectedItems.singleOrNull()
|
|
|
|
|
b.spinnerOriginalLocale.adapter = ArrayAdapter(
|
|
|
|
|
b.spinnerOriginalLocale.context,
|
|
|
|
|
android.R.layout.simple_spinner_dropdown_item,
|
|
|
|
|
android.R.id.text1,
|
|
|
|
|
value.availableItems.map { it.getDisplayName(b.spinnerOriginalLocale.context) },
|
|
|
|
|
)
|
|
|
|
|
val selectedIndex = value.availableItems.indexOf(selected)
|
|
|
|
|
if (selectedIndex >= 0) {
|
|
|
|
|
b.spinnerOriginalLocale.setSelection(selectedIndex, false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun onSortOrderChanged(value: FilterProperty<SortOrder>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutOrder.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val selected = value.selectedItems.single()
|
|
|
|
|
b.spinnerOrder.adapter = ArrayAdapter(
|
|
|
|
|
b.spinnerOrder.context,
|
|
|
|
|
android.R.layout.simple_spinner_dropdown_item,
|
|
|
|
|
android.R.id.text1,
|
|
|
|
|
value.availableItems.map { b.spinnerOrder.context.getString(it.titleRes) },
|
|
|
|
|
)
|
|
|
|
|
val selectedIndex = value.availableItems.indexOf(selected)
|
|
|
|
|
if (selectedIndex >= 0) {
|
|
|
|
|
b.spinnerOrder.setSelection(selectedIndex, false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private fun onTagsChanged(value: FilterProperty<MangaTag>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutGenres.isGone = value.isEmptyAndSuccess()
|
|
|
|
|
b.layoutGenres.setError(value.error?.getDisplayMessage(resources))
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val chips = value.availableItems.map { tag ->
|
|
|
|
|
ChipsView.ChipModel(
|
|
|
|
|
title = tag.title,
|
|
|
|
|
isChecked = tag in value.selectedItems,
|
|
|
|
|
data = tag,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
b.chipsGenres.setChips(chips)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun onLocaleChanged(value: FilterProperty<Locale?>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutLocale.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val selected = value.selectedItems.singleOrNull()
|
|
|
|
|
b.spinnerLocale.adapter = ArrayAdapter(
|
|
|
|
|
b.spinnerLocale.context,
|
|
|
|
|
android.R.layout.simple_spinner_dropdown_item,
|
|
|
|
|
android.R.id.text1,
|
|
|
|
|
value.availableItems.map { it.getDisplayName(b.spinnerLocale.context) },
|
|
|
|
|
)
|
|
|
|
|
val selectedIndex = value.availableItems.indexOf(selected)
|
|
|
|
|
if (selectedIndex >= 0) {
|
|
|
|
|
b.spinnerLocale.setSelection(selectedIndex, false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private fun onTagsExcludedChanged(value: FilterProperty<MangaTag>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutGenresExclude.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val chips = value.availableItems.map { tag ->
|
|
|
|
|
ChipsView.ChipModel(
|
|
|
|
|
title = tag.title,
|
|
|
|
|
isChecked = tag in value.selectedItems,
|
|
|
|
|
data = tag,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
b.chipsGenresExclude.setChips(chips)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun onOriginalLocaleChanged(value: FilterProperty<Locale?>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutOriginalLocale.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val selected = value.selectedItems.singleOrNull()
|
|
|
|
|
b.spinnerOriginalLocale.adapter = ArrayAdapter(
|
|
|
|
|
b.spinnerOriginalLocale.context,
|
|
|
|
|
android.R.layout.simple_spinner_dropdown_item,
|
|
|
|
|
android.R.id.text1,
|
|
|
|
|
value.availableItems.map { it.getDisplayName(b.spinnerOriginalLocale.context) },
|
|
|
|
|
)
|
|
|
|
|
val selectedIndex = value.availableItems.indexOf(selected)
|
|
|
|
|
if (selectedIndex >= 0) {
|
|
|
|
|
b.spinnerOriginalLocale.setSelection(selectedIndex, false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private fun onStateChanged(value: FilterProperty<MangaState>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutState.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val chips = value.availableItems.map { state ->
|
|
|
|
|
ChipsView.ChipModel(
|
|
|
|
|
title = getString(state.titleResId),
|
|
|
|
|
isChecked = state in value.selectedItems,
|
|
|
|
|
data = state,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
b.chipsState.setChips(chips)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun onTagsChanged(value: FilterProperty<MangaTag>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutGenres.isGone = value.isEmptyAndSuccess()
|
|
|
|
|
b.layoutGenres.setError(value.error?.getDisplayMessage(resources))
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val chips = value.availableItems.map { tag ->
|
|
|
|
|
ChipsView.ChipModel(
|
|
|
|
|
title = tag.title,
|
|
|
|
|
isChecked = tag in value.selectedItems,
|
|
|
|
|
data = tag,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
b.chipsGenres.setChips(chips)
|
|
|
|
|
}
|
|
|
|
|
private fun onContentTypesChanged(value: FilterProperty<ContentType>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutTypes.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val chips = value.availableItems.map { type ->
|
|
|
|
|
ChipsView.ChipModel(
|
|
|
|
|
title = getString(type.titleResId),
|
|
|
|
|
isChecked = type in value.selectedItems,
|
|
|
|
|
data = type,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
b.chipsTypes.setChips(chips)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun onTagsExcludedChanged(value: FilterProperty<MangaTag>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutGenresExclude.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val chips = value.availableItems.map { tag ->
|
|
|
|
|
ChipsView.ChipModel(
|
|
|
|
|
title = tag.title,
|
|
|
|
|
isChecked = tag in value.selectedItems,
|
|
|
|
|
data = tag,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
b.chipsGenresExclude.setChips(chips)
|
|
|
|
|
}
|
|
|
|
|
private fun onContentRatingChanged(value: FilterProperty<ContentRating>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutContentRating.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val chips = value.availableItems.map { contentRating ->
|
|
|
|
|
ChipsView.ChipModel(
|
|
|
|
|
title = getString(contentRating.titleResId),
|
|
|
|
|
isChecked = contentRating in value.selectedItems,
|
|
|
|
|
data = contentRating,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
b.chipsContentRating.setChips(chips)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun onStateChanged(value: FilterProperty<MangaState>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutState.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val chips = value.availableItems.map { state ->
|
|
|
|
|
ChipsView.ChipModel(
|
|
|
|
|
title = getString(state.titleResId),
|
|
|
|
|
isChecked = state in value.selectedItems,
|
|
|
|
|
data = state,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
b.chipsState.setChips(chips)
|
|
|
|
|
}
|
|
|
|
|
private fun onDemographicsChanged(value: FilterProperty<Demographic>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutDemographics.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val chips = value.availableItems.map { demographic ->
|
|
|
|
|
ChipsView.ChipModel(
|
|
|
|
|
title = getString(demographic.titleResId),
|
|
|
|
|
isChecked = demographic in value.selectedItems,
|
|
|
|
|
data = demographic,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
b.chipsDemographics.setChips(chips)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun onContentTypesChanged(value: FilterProperty<ContentType>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutTypes.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val chips = value.availableItems.map { type ->
|
|
|
|
|
ChipsView.ChipModel(
|
|
|
|
|
title = getString(type.titleResId),
|
|
|
|
|
isChecked = type in value.selectedItems,
|
|
|
|
|
data = type,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
b.chipsTypes.setChips(chips)
|
|
|
|
|
}
|
|
|
|
|
private fun onYearChanged(value: FilterProperty<Int>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutYear.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val currentValue = value.selectedItems.singleOrNull() ?: YEAR_UNKNOWN
|
|
|
|
|
b.layoutYear.setValueText(
|
|
|
|
|
if (currentValue == YEAR_UNKNOWN) {
|
|
|
|
|
getString(R.string.any)
|
|
|
|
|
} else {
|
|
|
|
|
currentValue.toString()
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
b.sliderYear.valueFrom = value.availableItems.first().toFloat()
|
|
|
|
|
b.sliderYear.valueTo = value.availableItems.last().toFloat()
|
|
|
|
|
b.sliderYear.setValueRounded(currentValue.toFloat())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun onContentRatingChanged(value: FilterProperty<ContentRating>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutContentRating.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val chips = value.availableItems.map { contentRating ->
|
|
|
|
|
ChipsView.ChipModel(
|
|
|
|
|
title = getString(contentRating.titleResId),
|
|
|
|
|
isChecked = contentRating in value.selectedItems,
|
|
|
|
|
data = contentRating,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
b.chipsContentRating.setChips(chips)
|
|
|
|
|
}
|
|
|
|
|
private fun onYearRangeChanged(value: FilterProperty<Int>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutYearsRange.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
b.sliderYearsRange.valueFrom = value.availableItems.first().toFloat()
|
|
|
|
|
b.sliderYearsRange.valueTo = value.availableItems.last().toFloat()
|
|
|
|
|
val currentValueFrom = value.selectedItems.firstOrNull()?.toFloat() ?: b.sliderYearsRange.valueFrom
|
|
|
|
|
val currentValueTo = value.selectedItems.lastOrNull()?.toFloat() ?: b.sliderYearsRange.valueTo
|
|
|
|
|
b.layoutYearsRange.setValueText(
|
|
|
|
|
getString(
|
|
|
|
|
R.string.memory_usage_pattern,
|
|
|
|
|
currentValueFrom.toInt().toString(),
|
|
|
|
|
currentValueTo.toInt().toString(),
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
b.sliderYearsRange.setValuesRounded(currentValueFrom, currentValueTo)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun onDemographicsChanged(value: FilterProperty<Demographic>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutDemographics.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val chips = value.availableItems.map { demographic ->
|
|
|
|
|
ChipsView.ChipModel(
|
|
|
|
|
title = getString(demographic.titleResId),
|
|
|
|
|
isChecked = demographic in value.selectedItems,
|
|
|
|
|
data = demographic,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
b.chipsDemographics.setChips(chips)
|
|
|
|
|
}
|
|
|
|
|
private fun onSavedPresetsChanged(value: FilterProperty<PersistableFilter>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutSavedFilters.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val chips = value.availableItems.map { f ->
|
|
|
|
|
ChipsView.ChipModel(
|
|
|
|
|
title = f.name,
|
|
|
|
|
isChecked = f in value.selectedItems,
|
|
|
|
|
data = f,
|
|
|
|
|
isDropdown = true,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
b.chipsSavedFilters.setChips(chips)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun onYearChanged(value: FilterProperty<Int>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutYear.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
val currentValue = value.selectedItems.singleOrNull() ?: YEAR_UNKNOWN
|
|
|
|
|
b.layoutYear.setValueText(
|
|
|
|
|
if (currentValue == YEAR_UNKNOWN) {
|
|
|
|
|
getString(R.string.any)
|
|
|
|
|
} else {
|
|
|
|
|
currentValue.toString()
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
b.sliderYear.valueFrom = value.availableItems.first().toFloat()
|
|
|
|
|
b.sliderYear.valueTo = value.availableItems.last().toFloat()
|
|
|
|
|
b.sliderYear.setValueRounded(currentValue.toFloat())
|
|
|
|
|
}
|
|
|
|
|
private fun showSavedFilterMenu(anchor: View, preset: PersistableFilter) {
|
|
|
|
|
val menu = PopupMenu(context ?: return, anchor)
|
|
|
|
|
val filter = FilterCoordinator.require(this)
|
|
|
|
|
menu.inflate(R.menu.popup_saved_filter)
|
|
|
|
|
menu.setOnMenuItemClickListener { menuItem ->
|
|
|
|
|
when (menuItem.itemId) {
|
|
|
|
|
R.id.action_delete -> filter.deleteSavedFilter(preset.id)
|
|
|
|
|
R.id.action_rename -> onRenameFilterClick(preset)
|
|
|
|
|
}
|
|
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
menu.show()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun onYearRangeChanged(value: FilterProperty<Int>) {
|
|
|
|
|
val b = viewBinding ?: return
|
|
|
|
|
b.layoutYearsRange.isGone = value.isEmpty()
|
|
|
|
|
if (value.isEmpty()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
b.sliderYearsRange.valueFrom = value.availableItems.first().toFloat()
|
|
|
|
|
b.sliderYearsRange.valueTo = value.availableItems.last().toFloat()
|
|
|
|
|
val currentValueFrom = value.selectedItems.firstOrNull()?.toFloat() ?: b.sliderYearsRange.valueFrom
|
|
|
|
|
val currentValueTo = value.selectedItems.lastOrNull()?.toFloat() ?: b.sliderYearsRange.valueTo
|
|
|
|
|
b.layoutYearsRange.setValueText(
|
|
|
|
|
getString(
|
|
|
|
|
R.string.memory_usage_pattern,
|
|
|
|
|
currentValueFrom.toInt().toString(),
|
|
|
|
|
currentValueTo.toInt().toString(),
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
b.sliderYearsRange.setValuesRounded(currentValueFrom, currentValueTo)
|
|
|
|
|
}
|
|
|
|
|
private fun onSaveFilterClick() {
|
|
|
|
|
val filter = FilterCoordinator.require(this)
|
|
|
|
|
buildAlertDialog(context ?: return) {
|
|
|
|
|
val input = setEditText(
|
|
|
|
|
inputType = EditorInfo.TYPE_CLASS_TEXT or EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES,
|
|
|
|
|
singleLine = true,
|
|
|
|
|
)
|
|
|
|
|
input.setHint(R.string.enter_name)
|
|
|
|
|
input.filters += InputFilter.LengthFilter(MAX_TITLE_LENGTH)
|
|
|
|
|
setTitle(R.string.save_filter)
|
|
|
|
|
setPositiveButton(R.string.save) { d, _ ->
|
|
|
|
|
val text = input.text?.toString()?.trim()
|
|
|
|
|
if (!text.isNullOrEmpty()) {
|
|
|
|
|
filter.saveCurrentFilter(text)
|
|
|
|
|
} else {
|
|
|
|
|
Snackbar.make(
|
|
|
|
|
viewBinding?.scrollView ?: return@setPositiveButton,
|
|
|
|
|
R.string.invalid_value_message,
|
|
|
|
|
Snackbar.LENGTH_SHORT,
|
|
|
|
|
).show()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
setNegativeButton(android.R.string.cancel, null)
|
|
|
|
|
}.show()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun onRenameFilterClick(preset: PersistableFilter) {
|
|
|
|
|
val filter = FilterCoordinator.require(this)
|
|
|
|
|
buildAlertDialog(context ?: return) {
|
|
|
|
|
val input = setEditText(
|
|
|
|
|
inputType = EditorInfo.TYPE_CLASS_TEXT or EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES,
|
|
|
|
|
singleLine = true,
|
|
|
|
|
)
|
|
|
|
|
input.filters += InputFilter.LengthFilter(MAX_TITLE_LENGTH)
|
|
|
|
|
input.setHint(R.string.enter_name)
|
|
|
|
|
input.setText(preset.name)
|
|
|
|
|
setTitle(R.string.rename)
|
|
|
|
|
setPositiveButton(R.string.save) { _, _ ->
|
|
|
|
|
val text = input.text?.toString()?.trim()
|
|
|
|
|
if (!text.isNullOrEmpty()) {
|
|
|
|
|
filter.renameSavedFilter(preset.id, text)
|
|
|
|
|
} else {
|
|
|
|
|
Snackbar.make(
|
|
|
|
|
viewBinding?.scrollView ?: return@setPositiveButton,
|
|
|
|
|
R.string.invalid_value_message,
|
|
|
|
|
Snackbar.LENGTH_SHORT,
|
|
|
|
|
).show()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
setNegativeButton(android.R.string.cancel, null)
|
|
|
|
|
}.show()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|