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
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue