Skip to content

Commit

Permalink
feat: sort subscriptions in groups (#443)
Browse files Browse the repository at this point in the history
  • Loading branch information
sneazy-ibo authored Jun 25, 2024
1 parent 2180086 commit ae95b61
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 25 deletions.
33 changes: 12 additions & 21 deletions app/src/main/java/ani/dantotsu/settings/SubscriptionItem.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,46 +9,37 @@ import ani.dantotsu.loadImage
import ani.dantotsu.media.MediaDetailsActivity
import ani.dantotsu.notifications.subscription.SubscriptionHelper
import com.xwray.groupie.GroupieAdapter
import com.xwray.groupie.Item
import com.xwray.groupie.viewbinding.BindableItem

class SubscriptionItem(
val id: Int,
private val media: SubscriptionHelper.Companion.SubscribeMedia,
private val adapter: GroupieAdapter
private val adapter: GroupieAdapter,
private val onItemRemoved: (Int) -> Unit
) : BindableItem<ItemSubscriptionBinding>() {
private lateinit var binding: ItemSubscriptionBinding
override fun bind(p0: ItemSubscriptionBinding, p1: Int) {
val context = p0.root.context
binding = p0
val parserName = if (media.isAnime)
SubscriptionHelper.getAnimeParser(media.id).name
else
SubscriptionHelper.getMangaParser(media.id).name
val mediaName = media.name
val showName = "$mediaName ($parserName)"
binding.subscriptionName.text = showName

override fun bind(viewBinding: ItemSubscriptionBinding, position: Int) {
binding = viewBinding
val context = binding.root.context

binding.subscriptionName.text = media.name
binding.root.setOnClickListener {
ContextCompat.startActivity(
context,
Intent(context, MediaDetailsActivity::class.java).putExtra(
"mediaId", media.id
),
Intent(context, MediaDetailsActivity::class.java).putExtra("mediaId", media.id),
null
)
}
binding.subscriptionCover.loadImage(media.image)
binding.deleteSubscription.setOnClickListener {
SubscriptionHelper.deleteSubscription(id, true)
adapter.remove(this)
onItemRemoved(id)
}
}

override fun getLayout(): Int {
return R.layout.item_subscription
}
override fun getLayout(): Int = R.layout.item_subscription

override fun initializeViewBinding(p0: View): ItemSubscriptionBinding {
return ItemSubscriptionBinding.bind(p0)
}
override fun initializeViewBinding(view: View): ItemSubscriptionBinding = ItemSubscriptionBinding.bind(view)
}
113 changes: 113 additions & 0 deletions app/src/main/java/ani/dantotsu/settings/SubscriptionSource.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package ani.dantotsu.settings

import android.app.AlertDialog
import android.content.Context
import android.graphics.drawable.Drawable
import android.view.View
import android.view.ViewGroup
import ani.dantotsu.R
import ani.dantotsu.databinding.ItemExtensionBinding
import ani.dantotsu.notifications.subscription.SubscriptionHelper
import com.xwray.groupie.GroupieAdapter
import com.xwray.groupie.viewbinding.BindableItem

class SubscriptionSource(
private val parserName: String,
private val subscriptions: MutableList<SubscriptionHelper.Companion.SubscribeMedia>,
private val adapter: GroupieAdapter,
private var parserIcon: Drawable? = null,
private val onGroupRemoved: (SubscriptionSource) -> Unit
) : BindableItem<ItemExtensionBinding>() {
private lateinit var binding: ItemExtensionBinding
private var isExpanded = false

override fun bind(viewBinding: ItemExtensionBinding, position: Int) {
binding = viewBinding
binding.extensionNameTextView.text = parserName
updateSubscriptionCount()
binding.extensionSubscriptions.visibility = View.VISIBLE

binding.extensionSubscriptions.setOnClickListener(null)
binding.root.setOnClickListener {
isExpanded = !isExpanded
toggleSubscriptions()
}
binding.subscriptionCount.setOnClickListener {
showRemoveAllSubscriptionsDialog(it.context)
}
binding.extensionIconImageView.visibility = View.VISIBLE
val layoutParams = binding.extensionIconImageView.layoutParams as ViewGroup.MarginLayoutParams
layoutParams.leftMargin = 28
binding.extensionIconImageView.layoutParams = layoutParams

parserIcon?.let {
binding.extensionIconImageView.setImageDrawable(it)
} ?: run {
binding.extensionIconImageView.setImageResource(R.drawable.control_background_40dp)
}

binding.extensionPinImageView.visibility = View.GONE
binding.extensionVersionTextView.visibility = View.GONE
binding.closeTextView.visibility = View.GONE
binding.settingsImageView.visibility = View.GONE
}

private fun updateSubscriptionCount() {
binding.subscriptionCount.text = subscriptions.size.toString()
binding.subscriptionCount.visibility = if (subscriptions.isEmpty()) View.GONE else View.VISIBLE
}

private fun showRemoveAllSubscriptionsDialog(context: Context) {
AlertDialog.Builder(context, R.style.MyPopup)
.setTitle(R.string.remove_all_subscriptions)
.setMessage(context.getString(R.string.remove_all_subscriptions_desc, parserName))
.setPositiveButton(R.string.apply) { _, _ ->
removeAllSubscriptions()
}
.setNegativeButton(R.string.cancel, null)
.show()
}

private fun removeAllSubscriptions() {
subscriptions.forEach { subscription ->
SubscriptionHelper.deleteSubscription(subscription.id, false)
}
if (isExpanded) {
val startPosition = adapter.getAdapterPosition(this) + 1
repeat(subscriptions.size) {
adapter.removeGroupAtAdapterPosition(startPosition)
}
}
subscriptions.clear()
onGroupRemoved(this)
}

private fun removeSubscription(id: Any?) {
subscriptions.removeAll { it.id == id }
updateSubscriptionCount()
if (subscriptions.isEmpty()) {
onGroupRemoved(this)
} else {
adapter.notifyItemChanged(adapter.getAdapterPosition(this))
}
}

private fun toggleSubscriptions() {
val startPosition = adapter.getAdapterPosition(this) + 1
if (isExpanded) {
subscriptions.forEachIndexed { index, subscribeMedia ->
adapter.add(startPosition + index, SubscriptionItem(subscribeMedia.id, subscribeMedia, adapter) { removedId ->
removeSubscription(removedId)
})
}
} else {
repeat(subscriptions.size) {
adapter.removeGroupAtAdapterPosition(startPosition)
}
}
}

override fun getLayout(): Int = R.layout.item_extension

override fun initializeViewBinding(view: View): ItemExtensionBinding = ItemExtensionBinding.bind(view)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ani.dantotsu.settings

import android.graphics.drawable.Drawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
Expand All @@ -9,13 +10,21 @@ import ani.dantotsu.BottomSheetDialogFragment
import ani.dantotsu.R
import ani.dantotsu.databinding.BottomSheetRecyclerBinding
import ani.dantotsu.notifications.subscription.SubscriptionHelper
import ani.dantotsu.parsers.novel.NovelExtensionManager
import com.xwray.groupie.GroupieAdapter
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get

class SubscriptionsBottomDialog : BottomSheetDialogFragment() {
private var _binding: BottomSheetRecyclerBinding? = null
private val binding get() = _binding!!
private val adapter: GroupieAdapter = GroupieAdapter()
private var subscriptions: Map<Int, SubscriptionHelper.Companion.SubscribeMedia> = mapOf()
private val animeExtension: AnimeExtensionManager = Injekt.get()
private val mangaExtensions: MangaExtensionManager = Injekt.get()
private val novelExtensions: NovelExtensionManager = Injekt.get()

override fun onCreateView(
inflater: LayoutInflater,
Expand All @@ -36,8 +45,33 @@ class SubscriptionsBottomDialog : BottomSheetDialogFragment() {
val context = requireContext()
binding.title.text = context.getString(R.string.subscriptions)
binding.replyButton.visibility = View.GONE
subscriptions.forEach { (id, media) ->
adapter.add(SubscriptionItem(id, media, adapter))

val groupedSubscriptions = subscriptions.values.groupBy {
if (it.isAnime) SubscriptionHelper.getAnimeParser(it.id).name
else SubscriptionHelper.getMangaParser(it.id).name
}

groupedSubscriptions.forEach { (parserName, mediaList) ->
adapter.add(SubscriptionSource(
parserName,
mediaList.toMutableList(),
adapter,
getParserIcon(parserName)
) { group ->
adapter.remove(group)
})
}
}

private fun getParserIcon(parserName: String): Drawable? {
return when {
animeExtension.installedExtensionsFlow.value.any { it.name == parserName } ->
animeExtension.installedExtensionsFlow.value.find { it.name == parserName }?.icon
mangaExtensions.installedExtensionsFlow.value.any { it.name == parserName } ->
mangaExtensions.installedExtensionsFlow.value.find { it.name == parserName }?.icon
novelExtensions.installedExtensionsFlow.value.any { it.name == parserName } ->
novelExtensions.installedExtensionsFlow.value.find { it.name == parserName }?.icon
else -> null
}
}

Expand Down
22 changes: 21 additions & 1 deletion app/src/main/res/layout/item_extension.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="3dp"
android:layout_marginEnd="9dp"
tools:ignore="ContentDescription" />

<LinearLayout
Expand Down Expand Up @@ -53,6 +53,26 @@
tools:ignore="SmallSp" />
</LinearLayout>

<TextView
android:id="@+id/subscriptionCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="12dp"
android:fontFamily="@font/poppins_bold"
android:visibility="gone"/>

<ImageView
android:id="@+id/extensionSubscriptions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="0"
android:src="@drawable/ui_bg"
android:visibility="gone"
app:tint="?attr/colorOnBackground"
tools:ignore="ContentDescription"/>

<ImageView
android:id="@+id/closeTextView"
android:layout_width="wrap_content"
Expand Down
1 change: 0 additions & 1 deletion app/src/main/res/layout/item_subscription.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="16dp"
android:layout_marginHorizontal="8dp"
android:orientation="horizontal"
tools:ignore="UseCompoundDrawables">
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,8 @@
<string name="use_alarm_manager_reliable">Use Alarm Manager for reliable Notifications</string>
<string name="use_alarm_manager_confirm">Using Alarm Manger can help fight against battery optimization, but may consume more battery. It also requires the Alarm Manager permission.</string>
<string name="use">Use</string>
<string name="remove_all_subscriptions">Remove All Subscriptions</string>
<string name="remove_all_subscriptions_desc">Are you sure you want to remove all subscriptions for %1$s?</string>
<string name="checking_subscriptions">Notification for Checking Subscriptions</string>
<string name="subscriptions_checking_time_s">Subscriptions Update Frequency : %1$s</string>
<string name="subscriptions_checking_time">Subscriptions Update Frequency</string>
Expand Down

0 comments on commit ae95b61

Please sign in to comment.