Tune ui
parent
6e71f20470
commit
905c4b362c
@ -0,0 +1,51 @@
|
|||||||
|
package org.koitharu.kotatsu.settings.tracker
|
||||||
|
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.room.InvalidationTracker
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import okio.Closeable
|
||||||
|
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||||
|
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||||
|
import org.koitharu.kotatsu.core.db.TABLE_FAVOURITE_CATEGORIES
|
||||||
|
import org.koitharu.kotatsu.core.db.removeObserverAsync
|
||||||
|
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class TrackerSettingsViewModel @Inject constructor(
|
||||||
|
private val repository: TrackingRepository,
|
||||||
|
private val database: MangaDatabase,
|
||||||
|
) : BaseViewModel() {
|
||||||
|
|
||||||
|
val categoriesCount = MutableLiveData<IntArray?>(null)
|
||||||
|
|
||||||
|
init {
|
||||||
|
updateCategoriesCount()
|
||||||
|
val databaseObserver = DatabaseObserver(this)
|
||||||
|
addCloseable(databaseObserver)
|
||||||
|
launchJob(Dispatchers.Default) {
|
||||||
|
database.invalidationTracker.addObserver(databaseObserver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateCategoriesCount() {
|
||||||
|
launchJob(Dispatchers.Default) {
|
||||||
|
categoriesCount.postValue(repository.getCategoriesCount())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DatabaseObserver(private var vm: TrackerSettingsViewModel?) :
|
||||||
|
InvalidationTracker.Observer(arrayOf(TABLE_FAVOURITE_CATEGORIES)),
|
||||||
|
Closeable {
|
||||||
|
|
||||||
|
override fun onInvalidated(tables: MutableSet<String>) {
|
||||||
|
vm?.updateCategoriesCount()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
(vm ?: return).database.invalidationTracker.removeObserverAsync(this)
|
||||||
|
vm = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
package org.koitharu.kotatsu.settings.tracker.categories
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter
|
||||||
|
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||||
|
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||||
|
|
||||||
|
class TrackerCategoriesConfigAdapter(
|
||||||
|
listener: OnListItemClickListener<FavouriteCategory>,
|
||||||
|
) : AsyncListDifferDelegationAdapter<FavouriteCategory>(DiffCallback()) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
delegatesManager.addDelegate(trackerCategoryAD(listener))
|
||||||
|
}
|
||||||
|
|
||||||
|
class DiffCallback : DiffUtil.ItemCallback<FavouriteCategory>() {
|
||||||
|
|
||||||
|
override fun areItemsTheSame(oldItem: FavouriteCategory, newItem: FavouriteCategory): Boolean {
|
||||||
|
return oldItem.id == newItem.id
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: FavouriteCategory, newItem: FavouriteCategory): Boolean {
|
||||||
|
return oldItem.isTrackingEnabled == newItem.isTrackingEnabled && oldItem.title == newItem.title
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getChangePayload(oldItem: FavouriteCategory, newItem: FavouriteCategory): Any? {
|
||||||
|
return if (oldItem.isTrackingEnabled == newItem.isTrackingEnabled) {
|
||||||
|
super.getChangePayload(oldItem, newItem)
|
||||||
|
} else Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
package org.koitharu.kotatsu.settings.tracker.categories
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.fragment.app.FragmentManager
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import org.koitharu.kotatsu.R
|
||||||
|
import org.koitharu.kotatsu.base.ui.BaseBottomSheet
|
||||||
|
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||||
|
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||||
|
import org.koitharu.kotatsu.databinding.SheetBaseBinding
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class TrackerCategoriesConfigSheet :
|
||||||
|
BaseBottomSheet<SheetBaseBinding>(),
|
||||||
|
OnListItemClickListener<FavouriteCategory>,
|
||||||
|
View.OnClickListener {
|
||||||
|
|
||||||
|
private val viewModel by viewModels<TrackerCategoriesConfigViewModel>()
|
||||||
|
|
||||||
|
override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): SheetBaseBinding {
|
||||||
|
return SheetBaseBinding.inflate(inflater, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
binding.headerBar.setTitle(R.string.favourites_categories)
|
||||||
|
binding.buttonDone.isVisible = true
|
||||||
|
binding.buttonDone.setOnClickListener(this)
|
||||||
|
val adapter = TrackerCategoriesConfigAdapter(this)
|
||||||
|
binding.recyclerView.adapter = adapter
|
||||||
|
|
||||||
|
viewModel.content.observe(viewLifecycleOwner) { adapter.items = it }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemClick(item: FavouriteCategory, view: View) {
|
||||||
|
viewModel.toggleItem(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(v: View?) {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private const val TAG = "TrackerCategoriesConfigSheet"
|
||||||
|
|
||||||
|
fun show(fm: FragmentManager) = TrackerCategoriesConfigSheet().show(fm, TAG)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package org.koitharu.kotatsu.settings.tracker.categories
|
||||||
|
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||||
|
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||||
|
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
|
||||||
|
import org.koitharu.kotatsu.utils.asFlowLiveData
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class TrackerCategoriesConfigViewModel @Inject constructor(
|
||||||
|
private val favouritesRepository: FavouritesRepository,
|
||||||
|
) : BaseViewModel() {
|
||||||
|
|
||||||
|
val content = favouritesRepository.observeCategories()
|
||||||
|
.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, emptyList())
|
||||||
|
|
||||||
|
private var updateJob: Job? = null
|
||||||
|
|
||||||
|
fun toggleItem(category: FavouriteCategory) {
|
||||||
|
val prevJob = updateJob
|
||||||
|
updateJob = launchJob(Dispatchers.Default) {
|
||||||
|
prevJob?.join()
|
||||||
|
favouritesRepository.updateCategoryTracking(category.id, !category.isTrackingEnabled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package org.koitharu.kotatsu.settings.tracker.categories
|
||||||
|
|
||||||
|
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||||
|
import org.koitharu.kotatsu.base.ui.list.AdapterDelegateClickListenerAdapter
|
||||||
|
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||||
|
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||||
|
import org.koitharu.kotatsu.databinding.ItemCategoryCheckableMultipleBinding
|
||||||
|
|
||||||
|
fun trackerCategoryAD(
|
||||||
|
listener: OnListItemClickListener<FavouriteCategory>,
|
||||||
|
) = adapterDelegateViewBinding<FavouriteCategory, FavouriteCategory, ItemCategoryCheckableMultipleBinding>(
|
||||||
|
{ layoutInflater, parent -> ItemCategoryCheckableMultipleBinding.inflate(layoutInflater, parent, false) },
|
||||||
|
) {
|
||||||
|
val eventListener = AdapterDelegateClickListenerAdapter(this, listener)
|
||||||
|
itemView.setOnClickListener(eventListener)
|
||||||
|
|
||||||
|
bind {
|
||||||
|
binding.root.text = item.title
|
||||||
|
binding.root.isChecked = item.isTrackingEnabled
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue