Manage library grid size
This commit is contained in:
@@ -4,7 +4,7 @@ import org.koin.androidx.viewmodel.dsl.viewModel
|
||||
import org.koin.dsl.module
|
||||
import org.koitharu.kotatsu.library.domain.LibraryRepository
|
||||
import org.koitharu.kotatsu.library.ui.LibraryViewModel
|
||||
import org.koitharu.kotatsu.library.ui.config.LibraryCategoriesConfigViewModel
|
||||
import org.koitharu.kotatsu.library.ui.config.categories.LibraryCategoriesConfigViewModel
|
||||
|
||||
val libraryModule
|
||||
get() = module {
|
||||
|
||||
@@ -6,14 +6,15 @@ import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import androidx.core.view.MenuProvider
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import com.google.android.material.R as materialR
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.base.ui.dialog.RememberSelectionDialogListener
|
||||
import org.koitharu.kotatsu.library.ui.config.LibraryCategoriesConfigSheet
|
||||
import org.koitharu.kotatsu.utils.ext.startOfDay
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import com.google.android.material.R as materialR
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.base.ui.dialog.RememberSelectionDialogListener
|
||||
import org.koitharu.kotatsu.library.ui.config.categories.LibraryCategoriesConfigSheet
|
||||
import org.koitharu.kotatsu.library.ui.config.size.LibrarySizeBottomSheet
|
||||
import org.koitharu.kotatsu.utils.ext.startOfDay
|
||||
|
||||
class LibraryMenuProvider(
|
||||
private val context: Context,
|
||||
@@ -31,6 +32,10 @@ class LibraryMenuProvider(
|
||||
showClearHistoryDialog()
|
||||
true
|
||||
}
|
||||
R.id.action_grid_size -> {
|
||||
LibrarySizeBottomSheet.show(fragmentManager)
|
||||
true
|
||||
}
|
||||
R.id.action_categories -> {
|
||||
LibraryCategoriesConfigSheet.show(fragmentManager)
|
||||
true
|
||||
@@ -64,4 +69,4 @@ class LibraryMenuProvider(
|
||||
viewModel.clearHistory(minDate)
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.library.ui.config
|
||||
package org.koitharu.kotatsu.library.ui.config.categories
|
||||
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter
|
||||
@@ -29,4 +29,4 @@ class LibraryCategoriesConfigAdapter(
|
||||
} else Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.library.ui.config
|
||||
package org.koitharu.kotatsu.library.ui.config.categories
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
@@ -14,7 +14,9 @@ import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.databinding.SheetBaseBinding
|
||||
import org.koitharu.kotatsu.utils.BottomSheetToolbarController
|
||||
|
||||
class LibraryCategoriesConfigSheet : BaseBottomSheet<SheetBaseBinding>(), OnListItemClickListener<FavouriteCategory>,
|
||||
class LibraryCategoriesConfigSheet :
|
||||
BaseBottomSheet<SheetBaseBinding>(),
|
||||
OnListItemClickListener<FavouriteCategory>,
|
||||
View.OnClickListener {
|
||||
|
||||
private val viewModel by viewModel<LibraryCategoriesConfigViewModel>()
|
||||
@@ -53,4 +55,4 @@ class LibraryCategoriesConfigSheet : BaseBottomSheet<SheetBaseBinding>(), OnList
|
||||
|
||||
fun show(fm: FragmentManager) = LibraryCategoriesConfigSheet().show(fm, TAG)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.library.ui.config
|
||||
package org.koitharu.kotatsu.library.ui.config.categories
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -24,4 +24,4 @@ class LibraryCategoriesConfigViewModel(
|
||||
favouritesRepository.updateCategory(category.id, !category.isVisibleInLibrary)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.library.ui.config
|
||||
package org.koitharu.kotatsu.library.ui.config.categories
|
||||
|
||||
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||
import org.koitharu.kotatsu.base.ui.list.AdapterDelegateClickListenerAdapter
|
||||
@@ -9,9 +9,8 @@ import org.koitharu.kotatsu.databinding.ItemCategoryCheckableMultipleBinding
|
||||
fun libraryCategoryAD(
|
||||
listener: OnListItemClickListener<FavouriteCategory>,
|
||||
) = adapterDelegateViewBinding<FavouriteCategory, FavouriteCategory, ItemCategoryCheckableMultipleBinding>(
|
||||
{ layoutInflater, parent -> ItemCategoryCheckableMultipleBinding.inflate(layoutInflater, parent, false) }
|
||||
{ layoutInflater, parent -> ItemCategoryCheckableMultipleBinding.inflate(layoutInflater, parent, false) },
|
||||
) {
|
||||
|
||||
val eventListener = AdapterDelegateClickListenerAdapter(this, listener)
|
||||
itemView.setOnClickListener(eventListener)
|
||||
|
||||
@@ -19,4 +18,4 @@ fun libraryCategoryAD(
|
||||
binding.root.text = item.title
|
||||
binding.root.isChecked = item.isVisibleInLibrary
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.koitharu.kotatsu.library.ui.config.size
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import com.google.android.material.slider.LabelFormatter
|
||||
import com.google.android.material.slider.Slider
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.base.ui.BaseBottomSheet
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.databinding.SheetLibrarySizeBinding
|
||||
import org.koitharu.kotatsu.utils.ext.setValueRounded
|
||||
import org.koitharu.kotatsu.utils.progress.IntPercentLabelFormatter
|
||||
|
||||
class LibrarySizeBottomSheet :
|
||||
BaseBottomSheet<SheetLibrarySizeBinding>(),
|
||||
Slider.OnChangeListener,
|
||||
View.OnClickListener {
|
||||
|
||||
private val settings by inject<AppSettings>(mode = LazyThreadSafetyMode.NONE)
|
||||
private var labelFormatter: LabelFormatter? = null
|
||||
|
||||
override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): SheetLibrarySizeBinding {
|
||||
return SheetLibrarySizeBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
labelFormatter = IntPercentLabelFormatter(view.context)
|
||||
binding.sliderGrid.addOnChangeListener(this)
|
||||
binding.buttonSmall.setOnClickListener(this)
|
||||
binding.buttonLarge.setOnClickListener(this)
|
||||
|
||||
binding.sliderGrid.setValueRounded(settings.gridSize.toFloat())
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
labelFormatter = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onValueChange(slider: Slider, value: Float, fromUser: Boolean) {
|
||||
settings.gridSize = value.toInt()
|
||||
binding.textViewLabel.text = labelFormatter?.getFormattedValue(value)
|
||||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
when (v.id) {
|
||||
R.id.button_small -> binding.sliderGrid.value -= binding.sliderGrid.stepSize
|
||||
R.id.button_large -> binding.sliderGrid.value += binding.sliderGrid.stepSize
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val TAG = "LibrarySizeBottomSheet"
|
||||
|
||||
fun show(fm: FragmentManager) = LibrarySizeBottomSheet().show(fm, TAG)
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,85 @@
|
||||
package org.koitharu.kotatsu.list.ui
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.Resources
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.StyleRes
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import kotlin.math.roundToInt
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class ItemSizeResolver(resources: Resources, settings: AppSettings) {
|
||||
class ItemSizeResolver(resources: Resources, private val settings: AppSettings) {
|
||||
|
||||
private val scaleFactor = settings.gridSize / 100f
|
||||
private val gridWidth = resources.getDimension(R.dimen.preferred_grid_width)
|
||||
private val scaleFactor: Float
|
||||
get() = settings.gridSize / 100f
|
||||
|
||||
val cellWidth: Int
|
||||
get() = (gridWidth * scaleFactor).roundToInt()
|
||||
}
|
||||
|
||||
fun attachToView(lifecycleOwner: LifecycleOwner, view: View, textView: TextView?) {
|
||||
val observer = SizeObserver(view, textView)
|
||||
view.addOnAttachStateChangeListener(observer)
|
||||
lifecycleOwner.lifecycle.addObserver(observer)
|
||||
if (view.isAttachedToWindow) {
|
||||
observer.update()
|
||||
}
|
||||
}
|
||||
|
||||
private inner class SizeObserver(
|
||||
private val view: View,
|
||||
private val textView: TextView?,
|
||||
) : DefaultLifecycleObserver, SharedPreferences.OnSharedPreferenceChangeListener, View.OnAttachStateChangeListener {
|
||||
|
||||
private val widthThreshold = view.resources.getDimensionPixelSize(R.dimen.small_grid_width)
|
||||
|
||||
@StyleRes
|
||||
private var prevTextAppearance = 0
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||
if (key == AppSettings.KEY_GRID_SIZE) {
|
||||
update()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewAttachedToWindow(v: View?) {
|
||||
settings.subscribe(this)
|
||||
update()
|
||||
}
|
||||
|
||||
override fun onViewDetachedFromWindow(v: View?) {
|
||||
settings.unsubscribe(this)
|
||||
}
|
||||
|
||||
override fun onDestroy(owner: LifecycleOwner) {
|
||||
super.onDestroy(owner)
|
||||
settings.unsubscribe(this)
|
||||
view.removeOnAttachStateChangeListener(this)
|
||||
}
|
||||
|
||||
fun update() {
|
||||
val newWidth = cellWidth
|
||||
textView?.adjustTextAppearance(newWidth)
|
||||
view.updateLayoutParams {
|
||||
width = newWidth
|
||||
}
|
||||
}
|
||||
|
||||
private fun TextView.adjustTextAppearance(width: Int) {
|
||||
val textAppearanceResId = if (width < widthThreshold) {
|
||||
R.style.TextAppearance_Kotatsu_GridTitle_Small
|
||||
} else {
|
||||
R.style.TextAppearance_Kotatsu_GridTitle
|
||||
}
|
||||
if (textAppearanceResId != prevTextAppearance) {
|
||||
prevTextAppearance = textAppearanceResId
|
||||
setTextAppearance(textAppearanceResId)
|
||||
requestLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,14 +18,16 @@ import org.koitharu.kotatsu.databinding.DialogListModeBinding
|
||||
import org.koitharu.kotatsu.utils.ext.setValueRounded
|
||||
import org.koitharu.kotatsu.utils.progress.IntPercentLabelFormatter
|
||||
|
||||
class ListModeSelectDialog : AlertDialogFragment<DialogListModeBinding>(),
|
||||
CheckableButtonGroup.OnCheckedChangeListener, Slider.OnSliderTouchListener {
|
||||
class ListModeSelectDialog :
|
||||
AlertDialogFragment<DialogListModeBinding>(),
|
||||
CheckableButtonGroup.OnCheckedChangeListener,
|
||||
Slider.OnChangeListener {
|
||||
|
||||
private val settings by inject<AppSettings>(mode = LazyThreadSafetyMode.NONE)
|
||||
|
||||
override fun onInflateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?
|
||||
container: ViewGroup?,
|
||||
) = DialogListModeBinding.inflate(inflater, container, false)
|
||||
|
||||
override fun onBuildDialog(builder: MaterialAlertDialogBuilder) {
|
||||
@@ -45,7 +47,7 @@ class ListModeSelectDialog : AlertDialogFragment<DialogListModeBinding>(),
|
||||
|
||||
binding.sliderGrid.setLabelFormatter(IntPercentLabelFormatter(view.context))
|
||||
binding.sliderGrid.setValueRounded(settings.gridSize.toFloat())
|
||||
binding.sliderGrid.addOnSliderTouchListener(this)
|
||||
binding.sliderGrid.addOnChangeListener(this)
|
||||
|
||||
binding.checkableGroup.onCheckedChangeListener = this
|
||||
}
|
||||
@@ -62,10 +64,10 @@ class ListModeSelectDialog : AlertDialogFragment<DialogListModeBinding>(),
|
||||
settings.listMode = mode
|
||||
}
|
||||
|
||||
override fun onStartTrackingTouch(slider: Slider) = Unit
|
||||
|
||||
override fun onStopTrackingTouch(slider: Slider) {
|
||||
settings.gridSize = slider.value.toInt()
|
||||
override fun onValueChange(slider: Slider, value: Float, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
settings.gridSize = value.toInt()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -74,4 +76,4 @@ class ListModeSelectDialog : AlertDialogFragment<DialogListModeBinding>(),
|
||||
|
||||
fun show(fm: FragmentManager) = ListModeSelectDialog().show(fm, TAG)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.koitharu.kotatsu.list.ui.adapter
|
||||
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import coil.ImageLoader
|
||||
import com.google.android.material.badge.BadgeDrawable
|
||||
@@ -24,9 +23,8 @@ fun mangaGridItemAD(
|
||||
clickListener: OnListItemClickListener<Manga>,
|
||||
sizeResolver: ItemSizeResolver?,
|
||||
) = adapterDelegateViewBinding<MangaGridModel, ListModel, ItemMangaGridBinding>(
|
||||
{ inflater, parent -> ItemMangaGridBinding.inflate(inflater, parent, false) }
|
||||
{ inflater, parent -> ItemMangaGridBinding.inflate(inflater, parent, false) },
|
||||
) {
|
||||
|
||||
var badge: BadgeDrawable? = null
|
||||
|
||||
itemView.setOnClickListener {
|
||||
@@ -35,11 +33,7 @@ fun mangaGridItemAD(
|
||||
itemView.setOnLongClickListener {
|
||||
clickListener.onItemLongClick(item.manga, it)
|
||||
}
|
||||
if (sizeResolver != null) {
|
||||
itemView.updateLayoutParams {
|
||||
width = sizeResolver.cellWidth
|
||||
}
|
||||
}
|
||||
sizeResolver?.attachToView(lifecycleOwner, itemView, binding.textViewTitle)
|
||||
|
||||
bind { payloads ->
|
||||
binding.textViewTitle.text = item.title
|
||||
@@ -62,4 +56,4 @@ fun mangaGridItemAD(
|
||||
badge = null
|
||||
binding.imageViewCover.disposeImageRequest()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,4 +9,4 @@ class IntPercentLabelFormatter(context: Context) : LabelFormatter {
|
||||
private val pattern = context.getString(R.string.percent_string_pattern)
|
||||
|
||||
override fun getFormattedValue(value: Float) = pattern.format(value.toInt().toString())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user