Merge pull request #8841 from Isira-Seneviratne/Notification_mode_ListAdapter

Use ListAdapter in NotificationModeConfigAdapter.
pull/9598/merge
Stypox 2023-01-02 14:47:25 +01:00 zatwierdzone przez GitHub
commit b6488fe342
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
2 zmienionych plików z 79 dodań i 119 usunięć

Wyświetl plik

@ -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)
}
}

Wyświetl plik

@ -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 disposables = 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,28 +46,34 @@ 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.
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()
} }
override fun onDestroy() { override fun onDestroy() {
updaters.dispose() disposables.dispose()
super.onDestroy() super.onDestroy()
} }
@ -79,41 +92,20 @@ 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()) adapter.currentList.forEach { updateNotificationMode(it, newMode) }
updaters.add( }
CompositeDisposable(
subscriptions.map { item -> private fun updateNotificationMode(item: SubscriptionItem, @NotificationMode mode: Int) {
subscriptionManager.updateNotificationMode( disposables.add(
serviceId = item.serviceId, subscriptionManager.updateNotificationMode(item.serviceId, item.url, mode)
url = item.url, .subscribeOn(Schedulers.io())
mode = newMode
).subscribeOn(Schedulers.io())
.subscribe() .subscribe()
}
)
) )
} }
} }