diff --git a/app/src/main/java/org/schabi/newpipe/settings/notifications/NotificationModeConfigAdapter.kt b/app/src/main/java/org/schabi/newpipe/settings/notifications/NotificationModeConfigAdapter.kt index 6ae264bb5..f61aa72ab 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/notifications/NotificationModeConfigAdapter.kt +++ b/app/src/main/java/org/schabi/newpipe/settings/notifications/NotificationModeConfigAdapter.kt @@ -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,85 +17,46 @@ import org.schabi.newpipe.settings.notifications.NotificationModeConfigAdapter.S */ class NotificationModeConfigAdapter( private val listener: ModeToggleListener -) : RecyclerView.Adapter() { - - private val differ = AsyncListDiffer(this, DiffCallback()) - - init { - setHasStableIds(true) - } - - 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(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 = differ.currentList - - fun update(newData: List) { - differ.submitList( - newData.map { - SubscriptionItem( - id = it.uid, - title = it.name, - notificationMode = it.notificationMode, - serviceId = it.serviceId, - url = it.url - ) - } +) : ListAdapter(DiffCallback) { + override fun onCreateViewHolder(parent: ViewGroup, i: Int): SubscriptionHolder { + return SubscriptionHolder( + ItemNotificationConfigBinding + .inflate(LayoutInflater.from(parent.context), parent, false) ) } - data class SubscriptionItem( - val id: Long, - val title: String, - @NotificationMode - val notificationMode: Int, - val serviceId: Int, - val url: String - ) + override fun onBindViewHolder(holder: SubscriptionHolder, position: Int) { + holder.bind(currentList[position]) + } - class SubscriptionHolder( - itemView: View, - private val listener: ModeToggleListener - ) : RecyclerView.ViewHolder(itemView), View.OnClickListener { - - private val checkedTextView = itemView as CheckedTextView + fun update(newData: List) { + val items = newData.map { + SubscriptionItem(it.uid, it.name, it.notificationMode, it.serviceId, it.url) + } + submitList(items) + } + inner class SubscriptionHolder( + private val itemBinding: ItemNotificationConfigBinding + ) : RecyclerView.ViewHolder(itemBinding.root) { init { - itemView.setOnClickListener(this) + itemView.setOnClickListener { + val mode = if (itemBinding.root.isChecked) { + NotificationMode.DISABLED + } else { + NotificationMode.ENABLED + } + listener.onModeChange(bindingAdapterPosition, mode) + } } 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) + itemBinding.root.text = data.title + itemBinding.root.isChecked = data.notificationMode != NotificationMode.DISABLED } } - private class DiffCallback : DiffUtil.ItemCallback() { - + private object DiffCallback : DiffUtil.ItemCallback() { 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 +) diff --git a/app/src/main/java/org/schabi/newpipe/settings/notifications/NotificationModeConfigFragment.kt b/app/src/main/java/org/schabi/newpipe/settings/notifications/NotificationModeConfigFragment.kt index 9021fd68c..581768c30 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/notifications/NotificationModeConfigFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/settings/notifications/NotificationModeConfigFragment.kt @@ -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 disposables = 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,28 +46,34 @@ 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. + 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() } override fun onDestroy() { - updaters.dispose() + disposables.dispose() 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() { - 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()) - .subscribe() - } - ) + adapter.currentList.forEach { updateNotificationMode(it, newMode) } + } + + private fun updateNotificationMode(item: SubscriptionItem, @NotificationMode mode: Int) { + disposables.add( + subscriptionManager.updateNotificationMode(item.serviceId, item.url, mode) + .subscribeOn(Schedulers.io()) + .subscribe() ) } }