Improve quick filter behavior
This commit is contained in:
@@ -57,6 +57,8 @@ class MangaQueryBuilder(
|
||||
if (filterOptions.isNotEmpty()) {
|
||||
if (whereConditions.isEmpty()) {
|
||||
append(" WHERE")
|
||||
} else {
|
||||
append(" AND")
|
||||
}
|
||||
var isFirst = true
|
||||
val groupedOptions = filterOptions.groupBy { it.groupKey }
|
||||
@@ -97,10 +99,12 @@ class MangaQueryBuilder(
|
||||
}
|
||||
}.let { SimpleSQLiteQuery(it) }
|
||||
|
||||
private fun getConditionOrThrow(option: ListFilterOption): String =
|
||||
requireNotNull(conditionCallback.getCondition(option)) {
|
||||
private fun getConditionOrThrow(option: ListFilterOption): String = when (option) {
|
||||
is ListFilterOption.Inverted -> "NOT(${getConditionOrThrow(option.option)})"
|
||||
else -> requireNotNull(conditionCallback.getCondition(option)) {
|
||||
"Unsupported filter option $option"
|
||||
}
|
||||
}
|
||||
|
||||
fun interface ConditionCallback {
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.koitharu.kotatsu.core.ui.widgets
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.view.View.OnClickListener
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.DrawableRes
|
||||
@@ -11,8 +12,6 @@ import com.google.android.material.chip.Chip
|
||||
import com.google.android.material.chip.ChipDrawable
|
||||
import com.google.android.material.chip.ChipGroup
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.util.ext.castOrNull
|
||||
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
class ChipsView @JvmOverloads constructor(
|
||||
@@ -23,9 +22,7 @@ class ChipsView @JvmOverloads constructor(
|
||||
|
||||
private var isLayoutSuppressedCompat = false
|
||||
private var isLayoutCalledOnSuppressed = false
|
||||
private val chipOnClickListener = OnClickListener {
|
||||
onChipClickListener?.onChipClick(it as Chip, it.tag)
|
||||
}
|
||||
private val chipOnClickListener = InternalChipClickListener()
|
||||
private val chipOnCloseListener = OnClickListener {
|
||||
val chip = it as Chip
|
||||
val data = it.tag
|
||||
@@ -71,8 +68,8 @@ class ChipsView @JvmOverloads constructor(
|
||||
suppressLayoutCompat(true)
|
||||
try {
|
||||
for ((i, model) in items.withIndex()) {
|
||||
val chip = getChildAt(i) as Chip? ?: addChip()
|
||||
bindChip(chip, model)
|
||||
val chip = getChildAt(i) as DataChip? ?: addChip()
|
||||
chip.bind(model)
|
||||
}
|
||||
if (childCount > items.size) {
|
||||
removeViews(items.size, childCount - items.size)
|
||||
@@ -82,56 +79,7 @@ class ChipsView @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> getCheckedData(cls: Class<T>): Set<T> {
|
||||
val result = LinkedHashSet<T>(childCount)
|
||||
for (child in children) {
|
||||
if (child is Chip && child.isChecked) {
|
||||
result += cls.castOrNull(child.tag) ?: continue
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun bindChip(chip: Chip, model: ChipModel) {
|
||||
if (model.titleResId == 0) {
|
||||
chip.text = model.title
|
||||
} else {
|
||||
chip.setText(model.titleResId)
|
||||
}
|
||||
chip.isClickable = onChipClickListener != null || model.isCheckable
|
||||
chip.isCheckable = model.isCheckable
|
||||
if (model.icon == 0) {
|
||||
chip.chipIcon = null
|
||||
chip.isChipIconVisible = false
|
||||
} else {
|
||||
chip.setChipIconResource(model.icon)
|
||||
chip.isChipIconVisible = true
|
||||
}
|
||||
chip.isChecked = model.isChecked
|
||||
chip.isCheckedIconVisible = chip.isCheckable && model.icon == 0
|
||||
chip.isCloseIconVisible = if (onChipCloseClickListener != null || model.isDropdown) {
|
||||
chip.setCloseIconResource(
|
||||
if (model.isDropdown) R.drawable.ic_expand_more else materialR.drawable.ic_m3_chip_close,
|
||||
)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
chip.tag = model.data
|
||||
}
|
||||
|
||||
private fun addChip(): Chip {
|
||||
val chip = Chip(context)
|
||||
val drawable = ChipDrawable.createFromAttributes(context, null, 0, chipStyle)
|
||||
chip.setChipDrawable(drawable)
|
||||
chip.isChipIconVisible = false
|
||||
chip.setOnCloseIconClickListener(chipOnCloseListener)
|
||||
chip.setEnsureMinTouchTargetSize(false)
|
||||
chip.setOnClickListener(chipOnClickListener)
|
||||
chip.isElegantTextHeight = false
|
||||
addView(chip)
|
||||
return chip
|
||||
}
|
||||
private fun addChip() = DataChip(context).also { addView(it) }
|
||||
|
||||
private fun suppressLayoutCompat(suppress: Boolean) {
|
||||
isLayoutSuppressedCompat = suppress
|
||||
@@ -147,13 +95,71 @@ class ChipsView @JvmOverloads constructor(
|
||||
val title: CharSequence? = null,
|
||||
@StringRes val titleResId: Int = 0,
|
||||
@DrawableRes val icon: Int = 0,
|
||||
val isCheckable: Boolean = false,
|
||||
@ColorRes val tint: Int = 0,
|
||||
val isChecked: Boolean = false,
|
||||
val isDropdown: Boolean = false,
|
||||
val data: Any? = null,
|
||||
)
|
||||
|
||||
private inner class DataChip(context: Context) : Chip(context) {
|
||||
|
||||
private var model: ChipModel? = null
|
||||
|
||||
init {
|
||||
val drawable = ChipDrawable.createFromAttributes(context, null, 0, chipStyle)
|
||||
setChipDrawable(drawable)
|
||||
isChipIconVisible = false
|
||||
setOnCloseIconClickListener(chipOnCloseListener)
|
||||
setEnsureMinTouchTargetSize(false)
|
||||
setOnClickListener(chipOnClickListener)
|
||||
isElegantTextHeight = false
|
||||
}
|
||||
|
||||
fun bind(model: ChipModel) {
|
||||
this.model = model
|
||||
|
||||
if (model.titleResId == 0) {
|
||||
text = model.title
|
||||
} else {
|
||||
setText(model.titleResId)
|
||||
}
|
||||
isClickable = onChipClickListener != null
|
||||
if (model.isChecked) {
|
||||
isCheckable = true
|
||||
isChecked = true
|
||||
} else {
|
||||
isChecked = false
|
||||
isCheckable = false
|
||||
}
|
||||
if (model.icon == 0 || model.isChecked) {
|
||||
chipIcon = null
|
||||
isChipIconVisible = false
|
||||
} else {
|
||||
setChipIconResource(model.icon)
|
||||
isChipIconVisible = true
|
||||
}
|
||||
isCheckedIconVisible = model.isChecked
|
||||
isCloseIconVisible = if (onChipCloseClickListener != null || model.isDropdown) {
|
||||
setCloseIconResource(
|
||||
if (model.isDropdown) R.drawable.ic_expand_more else materialR.drawable.ic_m3_chip_close,
|
||||
)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
tag = model.data
|
||||
}
|
||||
|
||||
override fun toggle() = Unit
|
||||
}
|
||||
|
||||
private inner class InternalChipClickListener : OnClickListener {
|
||||
override fun onClick(v: View?) {
|
||||
val chip = v as? DataChip ?: return
|
||||
onChipClickListener?.onChipClick(chip, chip.tag)
|
||||
}
|
||||
}
|
||||
|
||||
fun interface OnChipClickListener {
|
||||
|
||||
fun onChipClick(chip: Chip, data: Any?)
|
||||
|
||||
@@ -195,8 +195,6 @@ abstract class FavouritesDao : MangaQueryBuilder.ConditionCallback {
|
||||
ListFilterOption.Macro.NEW_CHAPTERS -> "(SELECT chapters_new FROM tracks WHERE tracks.manga_id = favourites.manga_id) > 0"
|
||||
ListFilterOption.Macro.NSFW -> "manga.nsfw = 1"
|
||||
is ListFilterOption.Tag -> "EXISTS(SELECT * FROM manga_tags WHERE favourites.manga_id = manga_tags.manga_id AND tag_id = ${option.tagId})"
|
||||
ListFilterOption.Downloaded,
|
||||
is ListFilterOption.Favorite,
|
||||
ListFilterOption.Macro.FAVORITE -> null
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,7 +393,6 @@ class FilterCoordinator @Inject constructor(
|
||||
for (tag in tags) {
|
||||
val model = ChipsView.ChipModel(
|
||||
title = tag.title,
|
||||
isCheckable = true,
|
||||
isChecked = selectedTags.remove(tag),
|
||||
data = tag,
|
||||
)
|
||||
@@ -406,7 +405,6 @@ class FilterCoordinator @Inject constructor(
|
||||
for (tag in selectedTags) {
|
||||
val model = ChipsView.ChipModel(
|
||||
title = tag.title,
|
||||
isCheckable = true,
|
||||
isChecked = true,
|
||||
data = tag,
|
||||
)
|
||||
|
||||
@@ -39,7 +39,7 @@ class FilterHeaderFragment : BaseFragment<FragmentFilterHeaderBinding>(), ChipsV
|
||||
if (tag == null) {
|
||||
TagsCatalogSheet.show(parentFragmentManager, isExcludeTag = false)
|
||||
} else {
|
||||
filter.setTag(tag, chip.isChecked)
|
||||
filter.setTag(tag, !chip.isChecked)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,14 +78,14 @@ class FilterSheetFragment : BaseAdaptiveSheet<SheetFilterBinding>(),
|
||||
override fun onChipClick(chip: Chip, data: Any?) {
|
||||
val filter = requireFilter()
|
||||
when (data) {
|
||||
is MangaState -> filter.setState(data, chip.isChecked)
|
||||
is MangaState -> filter.setState(data, !chip.isChecked)
|
||||
is MangaTag -> if (chip.parentView?.id == R.id.chips_genresExclude) {
|
||||
filter.setTagExcluded(data, chip.isChecked)
|
||||
filter.setTagExcluded(data, !chip.isChecked)
|
||||
} else {
|
||||
filter.setTag(data, chip.isChecked)
|
||||
filter.setTag(data, !chip.isChecked)
|
||||
}
|
||||
|
||||
is ContentRating -> filter.setContentRating(data, chip.isChecked)
|
||||
is ContentRating -> filter.setContentRating(data, !chip.isChecked)
|
||||
null -> TagsCatalogSheet.show(childFragmentManager, chip.parentView?.id == R.id.chips_genresExclude)
|
||||
}
|
||||
}
|
||||
@@ -142,7 +142,6 @@ class FilterSheetFragment : BaseAdaptiveSheet<SheetFilterBinding>(),
|
||||
value.selectedItems.mapTo(chips) { tag ->
|
||||
ChipsView.ChipModel(
|
||||
title = tag.title,
|
||||
isCheckable = true,
|
||||
isChecked = true,
|
||||
data = tag,
|
||||
)
|
||||
@@ -151,7 +150,6 @@ class FilterSheetFragment : BaseAdaptiveSheet<SheetFilterBinding>(),
|
||||
if (tag !in value.selectedItems) {
|
||||
ChipsView.ChipModel(
|
||||
title = tag.title,
|
||||
isCheckable = true,
|
||||
isChecked = false,
|
||||
data = tag,
|
||||
)
|
||||
@@ -181,7 +179,6 @@ class FilterSheetFragment : BaseAdaptiveSheet<SheetFilterBinding>(),
|
||||
tint = 0,
|
||||
title = tag.title,
|
||||
icon = 0,
|
||||
isCheckable = true,
|
||||
isChecked = true,
|
||||
data = tag,
|
||||
)
|
||||
@@ -190,7 +187,6 @@ class FilterSheetFragment : BaseAdaptiveSheet<SheetFilterBinding>(),
|
||||
if (tag !in value.selectedItems) {
|
||||
ChipsView.ChipModel(
|
||||
title = tag.title,
|
||||
isCheckable = true,
|
||||
isChecked = false,
|
||||
data = tag,
|
||||
)
|
||||
@@ -217,7 +213,6 @@ class FilterSheetFragment : BaseAdaptiveSheet<SheetFilterBinding>(),
|
||||
val chips = value.availableItems.map { state ->
|
||||
ChipsView.ChipModel(
|
||||
title = getString(state.titleResId),
|
||||
isCheckable = true,
|
||||
isChecked = state in value.selectedItems,
|
||||
data = state,
|
||||
)
|
||||
@@ -235,7 +230,6 @@ class FilterSheetFragment : BaseAdaptiveSheet<SheetFilterBinding>(),
|
||||
val chips = value.availableItems.map { contentRating ->
|
||||
ChipsView.ChipModel(
|
||||
title = getString(contentRating.titleResId),
|
||||
isCheckable = true,
|
||||
isChecked = contentRating in value.selectedItems,
|
||||
data = contentRating,
|
||||
)
|
||||
|
||||
@@ -153,12 +153,12 @@ abstract class HistoryDao : MangaQueryBuilder.ConditionCallback {
|
||||
protected abstract fun observeAllImpl(query: SupportSQLiteQuery): Flow<List<HistoryWithManga>>
|
||||
|
||||
override fun getCondition(option: ListFilterOption): String? = when (option) {
|
||||
ListFilterOption.Downloaded -> null
|
||||
is ListFilterOption.Favorite -> "EXISTS(SELECT * FROM favourites WHERE history.manga_id = favourites.manga_id AND category_id = ${option.category.id})"
|
||||
ListFilterOption.Macro.COMPLETED -> "percent >= $PROGRESS_COMPLETED"
|
||||
ListFilterOption.Macro.NEW_CHAPTERS -> "(SELECT chapters_new FROM tracks WHERE tracks.manga_id = history.manga_id) > 0"
|
||||
ListFilterOption.Macro.FAVORITE -> "EXISTS(SELECT * FROM favourites WHERE history.manga_id = favourites.manga_id)"
|
||||
ListFilterOption.Macro.NSFW -> "manga.nsfw = 1"
|
||||
is ListFilterOption.Tag -> "EXISTS(SELECT * FROM manga_tags WHERE history.manga_id = manga_tags.manga_id AND tag_id = ${option.tagId})"
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,4 +87,15 @@ sealed interface ListFilterOption {
|
||||
override val groupKey: String
|
||||
get() = "_favcat"
|
||||
}
|
||||
|
||||
data class Inverted(
|
||||
val option: ListFilterOption,
|
||||
override val iconResId: Int,
|
||||
override val titleResId: Int,
|
||||
override val titleText: CharSequence?,
|
||||
) : ListFilterOption {
|
||||
|
||||
override val groupKey: String
|
||||
get() = "_inv" + option.groupKey
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ abstract class MangaListQuickFilter(
|
||||
override fun setFilterOption(option: ListFilterOption, isApplied: Boolean) {
|
||||
appliedFilter.value = ArraySet(appliedFilter.value).also {
|
||||
if (isApplied) {
|
||||
it.add(option)
|
||||
it.addNoConflicts(option)
|
||||
} else {
|
||||
it.remove(option)
|
||||
}
|
||||
@@ -35,7 +35,7 @@ abstract class MangaListQuickFilter(
|
||||
if (option in it) {
|
||||
it.remove(option)
|
||||
} else {
|
||||
it.add(option)
|
||||
it.addNoConflicts(option)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,6 @@ abstract class MangaListQuickFilter(
|
||||
title = option.titleText,
|
||||
titleResId = option.titleResId,
|
||||
icon = option.iconResId,
|
||||
isCheckable = true,
|
||||
isChecked = option in selectedOptions,
|
||||
data = option,
|
||||
)
|
||||
@@ -68,4 +67,13 @@ abstract class MangaListQuickFilter(
|
||||
}
|
||||
|
||||
protected abstract suspend fun getAvailableFilterOptions(): List<ListFilterOption>
|
||||
|
||||
private fun ArraySet<ListFilterOption>.addNoConflicts(option: ListFilterOption) {
|
||||
add(option)
|
||||
if (option is ListFilterOption.Inverted) {
|
||||
remove(option.option)
|
||||
} else {
|
||||
removeIf { it is ListFilterOption.Inverted && it.option == option }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,8 +57,8 @@ class WelcomeSheet : BaseAdaptiveSheet<SheetWelcomeBinding>(), ChipsView.OnChipC
|
||||
|
||||
override fun onChipClick(chip: Chip, data: Any?) {
|
||||
when (data) {
|
||||
is ContentType -> viewModel.setTypeChecked(data, chip.isChecked)
|
||||
is Locale -> viewModel.setLocaleChecked(data, chip.isChecked)
|
||||
is ContentType -> viewModel.setTypeChecked(data, !chip.isChecked)
|
||||
is Locale -> viewModel.setLocaleChecked(data, !chip.isChecked)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,6 @@ class WelcomeSheet : BaseAdaptiveSheet<SheetWelcomeBinding>(), ChipsView.OnChipC
|
||||
value.availableItems.map {
|
||||
ChipsView.ChipModel(
|
||||
title = it.getDisplayName(chips.context),
|
||||
isCheckable = true,
|
||||
isChecked = it in value.selectedItems,
|
||||
data = it,
|
||||
)
|
||||
@@ -106,7 +105,6 @@ class WelcomeSheet : BaseAdaptiveSheet<SheetWelcomeBinding>(), ChipsView.OnChipC
|
||||
value.availableItems.map {
|
||||
ChipsView.ChipModel(
|
||||
title = getString(it.titleResId),
|
||||
isCheckable = true,
|
||||
isChecked = it in value.selectedItems,
|
||||
data = it,
|
||||
)
|
||||
|
||||
@@ -82,8 +82,8 @@ class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(),
|
||||
|
||||
override fun onChipClick(chip: Chip, data: Any?) {
|
||||
when (data) {
|
||||
is ContentType -> viewModel.setContentType(data, chip.isChecked)
|
||||
is Boolean -> viewModel.setNewOnly(chip.isChecked)
|
||||
is ContentType -> viewModel.setContentType(data, !chip.isChecked)
|
||||
is Boolean -> viewModel.setNewOnly(!chip.isChecked)
|
||||
else -> showLocalesMenu(chip)
|
||||
}
|
||||
}
|
||||
@@ -121,8 +121,7 @@ class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(),
|
||||
if (hasNewSources) {
|
||||
chips += ChipModel(
|
||||
title = getString(R.string._new),
|
||||
icon = R.drawable.ic_updated_selector,
|
||||
isCheckable = true,
|
||||
icon = R.drawable.ic_updated,
|
||||
isChecked = appliedFilter.isNewOnly,
|
||||
data = true,
|
||||
)
|
||||
@@ -133,7 +132,6 @@ class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(),
|
||||
}
|
||||
chips += ChipModel(
|
||||
title = getString(type.titleResId),
|
||||
isCheckable = true,
|
||||
isChecked = type in appliedFilter.types,
|
||||
data = type,
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.koitharu.kotatsu.suggestions.domain
|
||||
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.list.domain.ListFilterOption
|
||||
import org.koitharu.kotatsu.list.domain.MangaListQuickFilter
|
||||
@@ -16,6 +17,14 @@ class SuggestionsListQuickFilter @Inject constructor(
|
||||
}
|
||||
if (!settings.isNsfwContentDisabled && !settings.isSuggestionsExcludeNsfw) {
|
||||
add(ListFilterOption.Macro.NSFW)
|
||||
add(
|
||||
ListFilterOption.Inverted(
|
||||
option = ListFilterOption.Macro.NSFW,
|
||||
iconResId = R.drawable.ic_sfw,
|
||||
titleResId = R.string.sfw,
|
||||
titleText = null,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
24
app/src/main/res/drawable/ic_sfw.xml
Normal file
24
app/src/main/res/drawable/ic_sfw.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportWidth="0.72"
|
||||
android:viewportHeight="0.72">
|
||||
<clip-path android:pathData="M0,0L0,0.72L0.72,0.72L0.72,0L0,0zM0.12164,0.00691L0.71326,0.59883L0.67518,0.63691L0.08326,0.045L0.12164,0.00691z" />
|
||||
<path
|
||||
android:fillColor="#0f0f0f"
|
||||
android:pathData="M0.14033,0.03836C0.13258,0.02803 0.1191,0.02382 0.10685,0.0279 0.0946,0.03198 0.08634,0.04344 0.08634,0.05635l0,0.23993c0,0.01656 0.01343,0.02999 0.02999,0.02999 0.01656,0 0.02999,-0.01343 0.02999,-0.02999L0.14632,0.14633l0.12596,0.16795c0.00775,0.01033 0.02123,0.01454 0.03348,0.01045C0.31801,0.32065 0.32627,0.30919 0.32627,0.29628L0.32627,0.05635c0,-0.01656 -0.01343,-0.02999 -0.02999,-0.02999 -0.01656,0 -0.02999,0.01343 -0.02999,0.02999l0,0.14995z" />
|
||||
<path
|
||||
android:fillColor="#0f0f0f"
|
||||
android:pathData="m0.44623,0.02636c-0.03313,0 -0.05998,0.02685 -0.05998,0.05998l0,0.05998c0,0.03313 0.02685,0.05998 0.05998,0.05998l0.11996,0l0,0.05998l-0.14995,0c-0.01656,0 -0.02999,0.01343 -0.02999,0.02999 0,0.01656 0.01343,0.02999 0.02999,0.02999l0.14995,0c0.03313,0 0.05998,-0.02686 0.05998,-0.05998l0,-0.05998c0,-0.03313 -0.02685,-0.05998 -0.05998,-0.05998l-0.11996,0l0,-0.05998l0.14995,0c0.01656,0 0.02999,-0.01343 0.02999,-0.02999 0,-0.01656 -0.01343,-0.02999 -0.02999,-0.02999z" />
|
||||
<path
|
||||
android:fillColor="#0f0f0f"
|
||||
android:pathData="m0.08634,0.41624c0,-0.01656 0.01343,-0.02999 0.02999,-0.02999l0.17994,0c0.01656,0 0.02999,0.01343 0.02999,0.02999 0,0.01656 -0.01343,0.02999 -0.02999,0.02999L0.14632,0.44623l0,0.05998l0.14995,0c0.01656,0 0.02999,0.01343 0.02999,0.02999 0,0.01656 -0.01343,0.02999 -0.02999,0.02999L0.14632,0.5662l0,0.08997c0,0.01656 -0.01343,0.02999 -0.02999,0.02999 -0.01656,0 -0.02999,-0.01343 -0.02999,-0.02999z" />
|
||||
<path
|
||||
android:fillColor="#0f0f0f"
|
||||
android:pathData="m0.44623,0.41624c0,-0.01656 -0.01343,-0.02999 -0.02999,-0.02999 -0.01656,0 -0.02999,0.01343 -0.02999,0.02999l0,0.23993c0,0.01348 0.00899,0.0253 0.02199,0.0289 0.01299,0.0036 0.02678,-0.00191 0.03372,-0.01347L0.50621,0.5645l0.06425,0.10709c0.00694,0.01156 0.02073,0.01707 0.03372,0.01347C0.61718,0.68147 0.62617,0.66965 0.62617,0.65617l0,-0.23993c0,-0.01656 -0.01343,-0.02999 -0.02999,-0.02999 -0.01656,0 -0.02999,0.01343 -0.02999,0.02999l0,0.13165L0.53193,0.49078C0.52651,0.48175 0.51675,0.47622 0.50621,0.47622c-0.01054,0 -0.0203,0.00553 -0.02572,0.01456L0.44623,0.54789Z" />
|
||||
<path
|
||||
android:fillColor="#0f0f0f"
|
||||
android:pathData="M0.045,0.0831 L0.0834,0.045 0.675,0.6369 0.6369,0.675Z" />
|
||||
</vector>
|
||||
@@ -675,4 +675,5 @@
|
||||
<string name="invalid_proxy_configuration">Invalid proxy configuration</string>
|
||||
<string name="show_quick_filters">Show quick filters</string>
|
||||
<string name="show_quick_filters_summary">Provides the ability to filter manga lists by certain parameters</string>
|
||||
<string name="sfw">SFW</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user