Use ListAdapter in NotificationModeConfigAdapter.
This commit is contained in:
parent
231e677b16
commit
fb1360b72a
2 changed files with 81 additions and 119 deletions
|
@ -1,15 +1,13 @@
|
|||
package org.schabi.newpipe.settings.notifications
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.CheckedTextView
|
||||
import androidx.recyclerview.widget.AsyncListDiffer
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.database.subscription.NotificationMode
|
||||
import org.schabi.newpipe.database.subscription.SubscriptionEntity
|
||||
import org.schabi.newpipe.databinding.ItemNotificationConfigBinding
|
||||
import org.schabi.newpipe.settings.notifications.NotificationModeConfigAdapter.SubscriptionHolder
|
||||
|
||||
/**
|
||||
|
@ -19,75 +17,31 @@ import org.schabi.newpipe.settings.notifications.NotificationModeConfigAdapter.S
|
|||
*/
|
||||
class NotificationModeConfigAdapter(
|
||||
private val listener: ModeToggleListener
|
||||
) : RecyclerView.Adapter<SubscriptionHolder>() {
|
||||
|
||||
private val differ = AsyncListDiffer(this, DiffCallback())
|
||||
|
||||
init {
|
||||
setHasStableIds(true)
|
||||
) : ListAdapter<SubscriptionItem, SubscriptionHolder>(DiffCallback) {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, i: Int): SubscriptionHolder {
|
||||
return SubscriptionHolder(
|
||||
ItemNotificationConfigBinding
|
||||
.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): SubscriptionHolder {
|
||||
val view = LayoutInflater.from(viewGroup.context)
|
||||
.inflate(R.layout.item_notification_config, viewGroup, false)
|
||||
return SubscriptionHolder(view, listener)
|
||||
override fun onBindViewHolder(holder: SubscriptionHolder, position: Int) {
|
||||
holder.bind(currentList[position])
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(subscriptionHolder: SubscriptionHolder, i: Int) {
|
||||
subscriptionHolder.bind(differ.currentList[i])
|
||||
}
|
||||
|
||||
fun getItem(position: Int): SubscriptionItem = differ.currentList[position]
|
||||
|
||||
override fun getItemCount() = differ.currentList.size
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
return differ.currentList[position].id
|
||||
}
|
||||
|
||||
fun getCurrentList(): List<SubscriptionItem> = differ.currentList
|
||||
|
||||
fun update(newData: List<SubscriptionEntity>) {
|
||||
differ.submitList(
|
||||
newData.map {
|
||||
SubscriptionItem(
|
||||
id = it.uid,
|
||||
title = it.name,
|
||||
notificationMode = it.notificationMode,
|
||||
serviceId = it.serviceId,
|
||||
url = it.url
|
||||
)
|
||||
val items = newData.map {
|
||||
SubscriptionItem(it.uid, it.name, it.notificationMode, it.serviceId, it.url)
|
||||
}
|
||||
)
|
||||
submitList(items)
|
||||
}
|
||||
|
||||
data class SubscriptionItem(
|
||||
val id: Long,
|
||||
val title: String,
|
||||
@NotificationMode
|
||||
val notificationMode: Int,
|
||||
val serviceId: Int,
|
||||
val url: String
|
||||
)
|
||||
|
||||
class SubscriptionHolder(
|
||||
itemView: View,
|
||||
private val listener: ModeToggleListener
|
||||
) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
|
||||
|
||||
private val checkedTextView = itemView as CheckedTextView
|
||||
|
||||
inner class SubscriptionHolder(
|
||||
private val itemBinding: ItemNotificationConfigBinding
|
||||
) : RecyclerView.ViewHolder(itemBinding.root) {
|
||||
init {
|
||||
itemView.setOnClickListener(this)
|
||||
}
|
||||
|
||||
fun bind(data: SubscriptionItem) {
|
||||
checkedTextView.text = data.title
|
||||
checkedTextView.isChecked = data.notificationMode != NotificationMode.DISABLED
|
||||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
val mode = if (checkedTextView.isChecked) {
|
||||
itemView.setOnClickListener {
|
||||
val mode = if (itemBinding.root.isChecked) {
|
||||
NotificationMode.DISABLED
|
||||
} else {
|
||||
NotificationMode.ENABLED
|
||||
|
@ -96,8 +50,13 @@ class NotificationModeConfigAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
private class DiffCallback : DiffUtil.ItemCallback<SubscriptionItem>() {
|
||||
fun bind(data: SubscriptionItem) {
|
||||
itemBinding.root.text = data.title
|
||||
itemBinding.root.isChecked = data.notificationMode != NotificationMode.DISABLED
|
||||
}
|
||||
}
|
||||
|
||||
private object DiffCallback : DiffUtil.ItemCallback<SubscriptionItem>() {
|
||||
override fun areItemsTheSame(oldItem: SubscriptionItem, newItem: SubscriptionItem): Boolean {
|
||||
return oldItem.id == newItem.id
|
||||
}
|
||||
|
@ -107,18 +66,27 @@ class NotificationModeConfigAdapter(
|
|||
}
|
||||
|
||||
override fun getChangePayload(oldItem: SubscriptionItem, newItem: SubscriptionItem): Any? {
|
||||
if (oldItem.notificationMode != newItem.notificationMode) {
|
||||
return newItem.notificationMode
|
||||
return if (oldItem.notificationMode != newItem.notificationMode) {
|
||||
newItem.notificationMode
|
||||
} else {
|
||||
return super.getChangePayload(oldItem, newItem)
|
||||
super.getChangePayload(oldItem, newItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface ModeToggleListener {
|
||||
fun interface ModeToggleListener {
|
||||
/**
|
||||
* Triggered when the UI representation of a notification mode is changed.
|
||||
*/
|
||||
fun onModeChange(position: Int, @NotificationMode mode: Int)
|
||||
}
|
||||
}
|
||||
|
||||
data class SubscriptionItem(
|
||||
val id: Long,
|
||||
val title: String,
|
||||
@NotificationMode
|
||||
val notificationMode: Int,
|
||||
val serviceId: Int,
|
||||
val url: String
|
||||
)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.schabi.newpipe.settings.notifications
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
|
@ -8,30 +9,36 @@ import android.view.MenuItem
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.disposables.Disposable
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.database.subscription.NotificationMode
|
||||
import org.schabi.newpipe.databinding.FragmentChannelsNotificationsBinding
|
||||
import org.schabi.newpipe.local.subscription.SubscriptionManager
|
||||
import org.schabi.newpipe.settings.notifications.NotificationModeConfigAdapter.ModeToggleListener
|
||||
|
||||
/**
|
||||
* [NotificationModeConfigFragment] is a settings fragment
|
||||
* which allows changing the [NotificationMode] of all subscribed channels.
|
||||
* The [NotificationMode] can either be changed one by one or toggled for all channels.
|
||||
*/
|
||||
class NotificationModeConfigFragment : Fragment(), ModeToggleListener {
|
||||
class NotificationModeConfigFragment : Fragment() {
|
||||
private var _binding: FragmentChannelsNotificationsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
private lateinit var updaters: CompositeDisposable
|
||||
private val updaters = CompositeDisposable()
|
||||
private var loader: Disposable? = null
|
||||
private var adapter: NotificationModeConfigAdapter? = null
|
||||
private lateinit var adapter: NotificationModeConfigAdapter
|
||||
private lateinit var subscriptionManager: SubscriptionManager
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
subscriptionManager = SubscriptionManager(context)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
updaters = CompositeDisposable()
|
||||
setHasOptionsMenu(true)
|
||||
}
|
||||
|
||||
|
@ -39,23 +46,29 @@ class NotificationModeConfigFragment : Fragment(), ModeToggleListener {
|
|||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?,
|
||||
): View = inflater.inflate(R.layout.fragment_channels_notifications, container, false)
|
||||
): View {
|
||||
_binding = FragmentChannelsNotificationsBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
val recyclerView: RecyclerView = view.findViewById(R.id.recycler_view)
|
||||
adapter = NotificationModeConfigAdapter(this)
|
||||
recyclerView.adapter = adapter
|
||||
adapter = NotificationModeConfigAdapter { position, mode ->
|
||||
// Notification mode has been changed via the UI.
|
||||
// Now change it in the database.
|
||||
updaters.add(updateNotificationMode(adapter.currentList[position], mode))
|
||||
}
|
||||
binding.recyclerView.adapter = adapter
|
||||
loader?.dispose()
|
||||
loader = SubscriptionManager(requireContext())
|
||||
.subscriptions()
|
||||
loader = subscriptionManager.subscriptions()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { newData -> adapter?.update(newData) }
|
||||
.subscribe(adapter::update)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
loader?.dispose()
|
||||
loader = null
|
||||
_binding = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
@ -79,41 +92,22 @@ class NotificationModeConfigFragment : Fragment(), ModeToggleListener {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onModeChange(position: Int, @NotificationMode mode: Int) {
|
||||
// Notification mode has been changed via the UI.
|
||||
// Now change it in the database.
|
||||
val subscription = adapter?.getItem(position) ?: return
|
||||
updaters.add(
|
||||
SubscriptionManager(requireContext())
|
||||
.updateNotificationMode(
|
||||
subscription.serviceId,
|
||||
subscription.url,
|
||||
mode
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe()
|
||||
)
|
||||
}
|
||||
|
||||
private fun toggleAll() {
|
||||
val subscriptions = adapter?.getCurrentList() ?: return
|
||||
val mode = subscriptions.firstOrNull()?.notificationMode ?: return
|
||||
val mode = adapter.currentList.firstOrNull()?.notificationMode ?: return
|
||||
val newMode = when (mode) {
|
||||
NotificationMode.DISABLED -> NotificationMode.ENABLED
|
||||
else -> NotificationMode.DISABLED
|
||||
}
|
||||
val subscriptionManager = SubscriptionManager(requireContext())
|
||||
updaters.add(
|
||||
CompositeDisposable(
|
||||
subscriptions.map { item ->
|
||||
subscriptionManager.updateNotificationMode(
|
||||
serviceId = item.serviceId,
|
||||
url = item.url,
|
||||
mode = newMode
|
||||
).subscribeOn(Schedulers.io())
|
||||
val disposables = adapter.currentList.map { updateNotificationMode(it, newMode) }
|
||||
updaters.add(CompositeDisposable(disposables))
|
||||
}
|
||||
|
||||
private fun updateNotificationMode(
|
||||
item: SubscriptionItem,
|
||||
@NotificationMode mode: Int
|
||||
): Disposable {
|
||||
return subscriptionManager.updateNotificationMode(item.serviceId, item.url, mode)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe()
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue