1
0
mirror of https://github.com/TeamNewPipe/NewPipe synced 2024-11-05 17:46:24 +00:00

Use ListAdapter in NotificationModeConfigAdapter.

This commit is contained in:
Isira Seneviratne 2022-08-18 20:42:29 +05:30
parent 231e677b16
commit fb1360b72a
2 changed files with 81 additions and 119 deletions

View File

@ -1,15 +1,13 @@
package org.schabi.newpipe.settings.notifications package org.schabi.newpipe.settings.notifications
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.CheckedTextView
import androidx.recyclerview.widget.AsyncListDiffer
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import org.schabi.newpipe.R
import org.schabi.newpipe.database.subscription.NotificationMode import org.schabi.newpipe.database.subscription.NotificationMode
import org.schabi.newpipe.database.subscription.SubscriptionEntity import org.schabi.newpipe.database.subscription.SubscriptionEntity
import org.schabi.newpipe.databinding.ItemNotificationConfigBinding
import org.schabi.newpipe.settings.notifications.NotificationModeConfigAdapter.SubscriptionHolder import org.schabi.newpipe.settings.notifications.NotificationModeConfigAdapter.SubscriptionHolder
/** /**
@ -19,46 +17,69 @@ import org.schabi.newpipe.settings.notifications.NotificationModeConfigAdapter.S
*/ */
class NotificationModeConfigAdapter( class NotificationModeConfigAdapter(
private val listener: ModeToggleListener private val listener: ModeToggleListener
) : RecyclerView.Adapter<SubscriptionHolder>() { ) : ListAdapter<SubscriptionItem, SubscriptionHolder>(DiffCallback) {
override fun onCreateViewHolder(parent: ViewGroup, i: Int): SubscriptionHolder {
private val differ = AsyncListDiffer(this, DiffCallback()) return SubscriptionHolder(
ItemNotificationConfigBinding
init { .inflate(LayoutInflater.from(parent.context), parent, false)
setHasStableIds(true) )
} }
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): SubscriptionHolder { override fun onBindViewHolder(holder: SubscriptionHolder, position: Int) {
val view = LayoutInflater.from(viewGroup.context) holder.bind(currentList[position])
.inflate(R.layout.item_notification_config, viewGroup, false)
return SubscriptionHolder(view, listener)
} }
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>) { fun update(newData: List<SubscriptionEntity>) {
differ.submitList( val items = newData.map {
newData.map { SubscriptionItem(it.uid, it.name, it.notificationMode, it.serviceId, it.url)
SubscriptionItem( }
id = it.uid, submitList(items)
title = it.name, }
notificationMode = it.notificationMode,
serviceId = it.serviceId, inner class SubscriptionHolder(
url = it.url private val itemBinding: ItemNotificationConfigBinding
) ) : RecyclerView.ViewHolder(itemBinding.root) {
init {
itemView.setOnClickListener {
val mode = if (itemBinding.root.isChecked) {
NotificationMode.DISABLED
} else {
NotificationMode.ENABLED
}
listener.onModeChange(bindingAdapterPosition, mode)
}
}
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
}
override fun areContentsTheSame(oldItem: SubscriptionItem, newItem: SubscriptionItem): Boolean {
return oldItem == newItem
}
override fun getChangePayload(oldItem: SubscriptionItem, newItem: SubscriptionItem): Any? {
return if (oldItem.notificationMode != newItem.notificationMode) {
newItem.notificationMode
} else {
super.getChangePayload(oldItem, newItem)
}
}
}
fun interface ModeToggleListener {
/**
* Triggered when the UI representation of a notification mode is changed.
*/
fun onModeChange(position: Int, @NotificationMode mode: Int)
} }
)
} }
data class SubscriptionItem( data class SubscriptionItem(
@ -69,56 +90,3 @@ class NotificationModeConfigAdapter(
val serviceId: Int, val serviceId: Int,
val url: String val url: String
) )
class SubscriptionHolder(
itemView: View,
private val listener: ModeToggleListener
) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
private val checkedTextView = itemView as CheckedTextView
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) {
NotificationMode.DISABLED
} else {
NotificationMode.ENABLED
}
listener.onModeChange(bindingAdapterPosition, mode)
}
}
private class DiffCallback : DiffUtil.ItemCallback<SubscriptionItem>() {
override fun areItemsTheSame(oldItem: SubscriptionItem, newItem: SubscriptionItem): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: SubscriptionItem, newItem: SubscriptionItem): Boolean {
return oldItem == newItem
}
override fun getChangePayload(oldItem: SubscriptionItem, newItem: SubscriptionItem): Any? {
if (oldItem.notificationMode != newItem.notificationMode) {
return newItem.notificationMode
} else {
return super.getChangePayload(oldItem, newItem)
}
}
}
interface ModeToggleListener {
/**
* Triggered when the UI representation of a notification mode is changed.
*/
fun onModeChange(position: Int, @NotificationMode mode: Int)
}
}

View File

@ -1,5 +1,6 @@
package org.schabi.newpipe.settings.notifications package org.schabi.newpipe.settings.notifications
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
@ -8,30 +9,36 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.RecyclerView
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.Disposable import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.schedulers.Schedulers import io.reactivex.rxjava3.schedulers.Schedulers
import org.schabi.newpipe.R import org.schabi.newpipe.R
import org.schabi.newpipe.database.subscription.NotificationMode import org.schabi.newpipe.database.subscription.NotificationMode
import org.schabi.newpipe.databinding.FragmentChannelsNotificationsBinding
import org.schabi.newpipe.local.subscription.SubscriptionManager import org.schabi.newpipe.local.subscription.SubscriptionManager
import org.schabi.newpipe.settings.notifications.NotificationModeConfigAdapter.ModeToggleListener
/** /**
* [NotificationModeConfigFragment] is a settings fragment * [NotificationModeConfigFragment] is a settings fragment
* which allows changing the [NotificationMode] of all subscribed channels. * which allows changing the [NotificationMode] of all subscribed channels.
* The [NotificationMode] can either be changed one by one or toggled for all 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 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?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
updaters = CompositeDisposable()
setHasOptionsMenu(true) setHasOptionsMenu(true)
} }
@ -39,23 +46,29 @@ class NotificationModeConfigFragment : Fragment(), ModeToggleListener {
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle?, 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?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val recyclerView: RecyclerView = view.findViewById(R.id.recycler_view) adapter = NotificationModeConfigAdapter { position, mode ->
adapter = NotificationModeConfigAdapter(this) // Notification mode has been changed via the UI.
recyclerView.adapter = adapter // Now change it in the database.
updaters.add(updateNotificationMode(adapter.currentList[position], mode))
}
binding.recyclerView.adapter = adapter
loader?.dispose() loader?.dispose()
loader = SubscriptionManager(requireContext()) loader = subscriptionManager.subscriptions()
.subscriptions()
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe { newData -> adapter?.update(newData) } .subscribe(adapter::update)
} }
override fun onDestroyView() { override fun onDestroyView() {
loader?.dispose() loader?.dispose()
loader = null loader = null
_binding = null
super.onDestroyView() 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() { private fun toggleAll() {
val subscriptions = adapter?.getCurrentList() ?: return val mode = adapter.currentList.firstOrNull()?.notificationMode ?: return
val mode = subscriptions.firstOrNull()?.notificationMode ?: return
val newMode = when (mode) { val newMode = when (mode) {
NotificationMode.DISABLED -> NotificationMode.ENABLED NotificationMode.DISABLED -> NotificationMode.ENABLED
else -> NotificationMode.DISABLED else -> NotificationMode.DISABLED
} }
val subscriptionManager = SubscriptionManager(requireContext()) val disposables = adapter.currentList.map { updateNotificationMode(it, newMode) }
updaters.add( updaters.add(CompositeDisposable(disposables))
CompositeDisposable( }
subscriptions.map { item ->
subscriptionManager.updateNotificationMode( private fun updateNotificationMode(
serviceId = item.serviceId, item: SubscriptionItem,
url = item.url, @NotificationMode mode: Int
mode = newMode ): Disposable {
).subscribeOn(Schedulers.io()) return subscriptionManager.updateNotificationMode(item.serviceId, item.url, mode)
.subscribeOn(Schedulers.io())
.subscribe() .subscribe()
} }
)
)
}
} }