Skip to content

Commit

Permalink
feat: view subscriptions in settings
Browse files Browse the repository at this point in the history
  • Loading branch information
rebelonion committed May 17, 2024
1 parent f1d16ba commit 6c1176a
Show file tree
Hide file tree
Showing 14 changed files with 221 additions and 15 deletions.
2 changes: 2 additions & 0 deletions app/src/main/java/ani/dantotsu/Network.kt
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ data class FileUrl(
operator fun get(url: String?, headers: Map<String, String> = mapOf()): FileUrl? {
return FileUrl(url ?: return null, headers)
}

private const val serialVersionUID = 1L
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
val tDownloads = downloadManager.animeDownloadedTypes.filter { it.titleName.findValidName() == title }
val download = tDownloads.firstOrNull() ?: continue
val offlineAnimeModel = loadOfflineAnimeModel(download)
if (offlineAnimeModel.title == "unknown") offlineAnimeModel.title = title
newAnimeDownloads += offlineAnimeModel
}
downloads = newAnimeDownloads
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package ani.dantotsu.download.anime
import android.net.Uri

data class OfflineAnimeModel(
val title: String,
var title: String,
val score: String,
val totalEpisode: String,
val totalEpisodeList: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ import ani.dantotsu.currContext
import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaNameAdapter
import ani.dantotsu.media.Selected
import ani.dantotsu.media.emptyMedia
import ani.dantotsu.parsers.AnimeParser
import ani.dantotsu.parsers.AnimeSources
import ani.dantotsu.parsers.BaseParser
import ani.dantotsu.parsers.Episode
import ani.dantotsu.parsers.MangaChapter
import ani.dantotsu.parsers.MangaParser
import ani.dantotsu.parsers.MangaSources
import ani.dantotsu.parsers.ShowResponse
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.toast
import ani.dantotsu.tryWithSuspend
import ani.dantotsu.util.Logger
import kotlinx.coroutines.withTimeoutOrNull
Expand Down Expand Up @@ -50,16 +54,18 @@ class SubscriptionHelper {

suspend fun getEpisode(
parser: AnimeParser,
id: Int
subscribeMedia: SubscribeMedia
): Episode? {

val selected = loadSelected(id)
val selected = loadSelected(subscribeMedia.id)
val ep = withTimeoutOrNull(10 * 1000) {
tryWithSuspend {
val show = parser.loadSavedShowResponse(id) ?: throw Exception(
val show = parser.loadSavedShowResponse(subscribeMedia.id)
?: forceLoadShowResponse(subscribeMedia, selected, parser)
?: throw Exception(
currContext()?.getString(
R.string.failed_to_load_data,
id
subscribeMedia.id
)
)
show.sAnime?.let {
Expand All @@ -73,7 +79,7 @@ class SubscriptionHelper {

return ep?.apply {
selected.latest = number.toFloat()
saveSelected(id, selected)
saveSelected(subscribeMedia.id, selected)
}
}

Expand All @@ -89,15 +95,17 @@ class SubscriptionHelper {

suspend fun getChapter(
parser: MangaParser,
id: Int
subscribeMedia: SubscribeMedia
): MangaChapter? {
val selected = loadSelected(id)
val selected = loadSelected(subscribeMedia.id)
val chp = withTimeoutOrNull(10 * 1000) {
tryWithSuspend {
val show = parser.loadSavedShowResponse(id) ?: throw Exception(
val show = parser.loadSavedShowResponse(subscribeMedia.id)
?: forceLoadShowResponse(subscribeMedia, selected, parser)
?: throw Exception(
currContext()?.getString(
R.string.failed_to_load_data,
id
subscribeMedia.id
)
)
show.sManga?.let {
Expand All @@ -111,10 +119,28 @@ class SubscriptionHelper {

return chp?.apply {
selected.latest = MediaNameAdapter.findChapterNumber(number) ?: 0f
saveSelected(id, selected)
saveSelected(subscribeMedia.id, selected)
}
}

private suspend fun forceLoadShowResponse(subscribeMedia: SubscribeMedia, selected: Selected, parser: BaseParser): ShowResponse? {
val tempMedia = Media(
id = subscribeMedia.id,
name = null,
nameRomaji = subscribeMedia.name,
userPreferredName = subscribeMedia.name,
isAdult = subscribeMedia.isAdult,
isFav = false,
isListPrivate = false,
userScore = 0,
userRepeat = 0,
format = null,
selected = selected
)
parser.autoSearch(tempMedia)
return parser.loadSavedShowResponse(subscribeMedia.id)
}

data class SubscribeMedia(
val isAnime: Boolean,
val isAdult: Boolean,
Expand All @@ -134,6 +160,19 @@ class SubscriptionHelper {
) as? Map<Int, SubscribeMedia>)
?: mapOf<Int, SubscribeMedia>().also { PrefManager.setCustomVal(SUBSCRIPTIONS, it) }

@Suppress("UNCHECKED_CAST")
fun deleteSubscription(id: Int, showSnack: Boolean = false) {
val data = PrefManager.getNullableCustomVal(
SUBSCRIPTIONS,
null,
Map::class.java
) as? MutableMap<Int, SubscribeMedia>
?: mutableMapOf()
data.remove(id)
PrefManager.setCustomVal(SUBSCRIPTIONS, data)
if (showSnack) toast(R.string.subscription_deleted)
}

@Suppress("UNCHECKED_CAST")
fun saveSubscription(media: Media, subscribed: Boolean) {
val data = PrefManager.getNullableCustomVal(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class SubscriptionNotificationTask : Task {
val ep: Episode? =
SubscriptionHelper.getEpisode(
parser,
media.id
media
)
if (ep != null) context.getString(R.string.episode) + "${ep.number}${
if (ep.title != null) " : ${ep.title}" else ""
Expand All @@ -113,7 +113,7 @@ class SubscriptionNotificationTask : Task {
val ep: MangaChapter? =
SubscriptionHelper.getChapter(
parser,
media.id
media
)
if (ep != null) ep.number + " " + context.getString(R.string.just_released) to null
else null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import ani.dantotsu.navBarHeight
import ani.dantotsu.notifications.TaskScheduler
import ani.dantotsu.notifications.anilist.AnilistNotificationWorker
import ani.dantotsu.notifications.comment.CommentNotificationWorker
import ani.dantotsu.notifications.subscription.SubscriptionHelper
import ani.dantotsu.notifications.subscription.SubscriptionNotificationWorker
import ani.dantotsu.openSettings
import ani.dantotsu.settings.saving.PrefManager
Expand Down Expand Up @@ -102,6 +103,19 @@ class SettingsNotificationActivity : AppCompatActivity() {
).scheduleAllTasks(context)
}
),
Settings(
type = 1,
name = getString(R.string.view_subscriptions),
desc = getString(R.string.view_subscriptions_desc),
icon = R.drawable.ic_round_search_24,
onClick = {
val subscriptions = SubscriptionHelper.getSubscriptions()
SubscriptionsBottomDialog.newInstance(subscriptions).show(
supportFragmentManager,
"subscriptions"
)
}
),
Settings(
type = 1,
name = getString(R.string.anilist_notification_filters),
Expand Down
52 changes: 52 additions & 0 deletions app/src/main/java/ani/dantotsu/settings/SubscriptionItem.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package ani.dantotsu.settings

import android.content.Intent
import android.view.View
import androidx.core.content.ContextCompat
import ani.dantotsu.R
import ani.dantotsu.databinding.ItemSubscriptionBinding
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
) : 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
binding.root.setOnClickListener {
ContextCompat.startActivity(
context,
Intent(context, MediaDetailsActivity::class.java).putExtra(
"mediaId", media.id
),
null
)
}
binding.deleteSubscription.setOnClickListener {
SubscriptionHelper.deleteSubscription(id, true)
adapter.remove(this)
}
}

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

override fun initializeViewBinding(p0: View): ItemSubscriptionBinding {
return ItemSubscriptionBinding.bind(p0)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package ani.dantotsu.settings

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import ani.dantotsu.BottomSheetDialogFragment
import ani.dantotsu.R
import ani.dantotsu.databinding.BottomSheetRecyclerBinding
import ani.dantotsu.notifications.subscription.SubscriptionHelper
import com.xwray.groupie.GroupieAdapter

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()

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = BottomSheetRecyclerBinding.inflate(inflater, container, false)
return _binding?.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding.repliesRecyclerView.adapter = adapter
binding.repliesRecyclerView.layoutManager = LinearLayoutManager(
context,
LinearLayoutManager.VERTICAL,
false
)
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))
}
}

override fun onDestroyView() {
_binding = null
super.onDestroyView()
}

companion object {
fun newInstance(subscriptions: Map<Int, SubscriptionHelper.Companion.SubscribeMedia>): SubscriptionsBottomDialog {
val dialog = SubscriptionsBottomDialog()
dialog.subscriptions = subscriptions
return dialog
}
}
}
2 changes: 2 additions & 0 deletions app/src/main/java/ani/dantotsu/settings/saving/PrefManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -395,9 +395,11 @@ object PrefManager {
val obj = ois.readObject() as T?
obj
} else {
Logger.log("Serialized data is null (key: $key)")
default
}
} catch (e: java.io.InvalidClassException) {
Logger.log(e)
try {
getPrefLocation(location).edit().remove(key).apply()
default
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,7 @@ interface SAnime : Serializable {
fun create(): SAnime {
return SAnimeImpl()
}

private const val serialVersionUID = 1L
}
}
2 changes: 2 additions & 0 deletions app/src/main/java/eu/kanade/tachiyomi/source/model/SManga.kt
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,7 @@ interface SManga : Serializable {
fun create(): SManga {
return SMangaImpl()
}

private const val serialVersionUID = 1L
}
}
4 changes: 2 additions & 2 deletions app/src/main/res/layout/activity_settings_notifications.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@
android:layout_weight="1"
android:fontFamily="@font/poppins_bold"
android:text="@string/notifications"
android:textSize="28sp" />
android:textSize="27sp" />

<ImageView
android:layout_width="96dp"
android:layout_height="96dp"
android:layout_marginEnd="20dp"
android:layout_marginEnd="14dp"
android:layout_marginBottom="20dp"
android:padding="24dp"
app:srcCompat="@drawable/ic_round_notifications_none_24"
Expand Down
32 changes: 32 additions & 0 deletions app/src/main/res/layout/item_subscription.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
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">

<TextView
android:id="@+id/subscriptionName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:fontFamily="@font/poppins_bold"
android:text="@string/placeholder"
android:textSize="16sp" />

<ImageView
android:id="@+id/deleteSubscription"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="8dp"
android:contentDescription="@string/delete"
android:src="@drawable/ic_circle_cancel"
app:tint="?attr/colorOnBackground" />

</LinearLayout>
4 changes: 4 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -991,4 +991,8 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
<string name="replies">Replies</string>
<string name="open_rules">Open Rules</string>
<string name="post_to_anilist_warning">By posting to AniList, you agree to the rules and guidelines of AniList</string>
<string name="view_subscriptions">View Subscriptions</string>
<string name="view_subscriptions_desc">View and edit all your subscriptions</string>
<string name="subscriptions">Subscriptions</string>
<string name="subscription_deleted">Subscription Deleted</string>
</resources>

0 comments on commit 6c1176a

Please sign in to comment.