diff --git a/app/src/main/java/ani/dantotsu/Network.kt b/app/src/main/java/ani/dantotsu/Network.kt index fbfc399b..ce536e8d 100644 --- a/app/src/main/java/ani/dantotsu/Network.kt +++ b/app/src/main/java/ani/dantotsu/Network.kt @@ -143,6 +143,8 @@ data class FileUrl( operator fun get(url: String?, headers: Map = mapOf()): FileUrl? { return FileUrl(url ?: return null, headers) } + + private const val serialVersionUID = 1L } } diff --git a/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt b/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt index e9877c02..cdf7e993 100644 --- a/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt +++ b/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt @@ -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 diff --git a/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeModel.kt b/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeModel.kt index 4823e2af..5e936b83 100644 --- a/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeModel.kt +++ b/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeModel.kt @@ -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, diff --git a/app/src/main/java/ani/dantotsu/notifications/subscription/SubscriptionHelper.kt b/app/src/main/java/ani/dantotsu/notifications/subscription/SubscriptionHelper.kt index 79f84381..08104de1 100644 --- a/app/src/main/java/ani/dantotsu/notifications/subscription/SubscriptionHelper.kt +++ b/app/src/main/java/ani/dantotsu/notifications/subscription/SubscriptionHelper.kt @@ -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 @@ -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 { @@ -73,7 +79,7 @@ class SubscriptionHelper { return ep?.apply { selected.latest = number.toFloat() - saveSelected(id, selected) + saveSelected(subscribeMedia.id, selected) } } @@ -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 { @@ -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, @@ -134,6 +160,19 @@ class SubscriptionHelper { ) as? Map) ?: mapOf().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 + ?: 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( diff --git a/app/src/main/java/ani/dantotsu/notifications/subscription/SubscriptionNotificationTask.kt b/app/src/main/java/ani/dantotsu/notifications/subscription/SubscriptionNotificationTask.kt index 4aff71b0..83345013 100644 --- a/app/src/main/java/ani/dantotsu/notifications/subscription/SubscriptionNotificationTask.kt +++ b/app/src/main/java/ani/dantotsu/notifications/subscription/SubscriptionNotificationTask.kt @@ -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 "" @@ -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 diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsNotificationActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsNotificationActivity.kt index 75659b99..2b417df0 100644 --- a/app/src/main/java/ani/dantotsu/settings/SettingsNotificationActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/SettingsNotificationActivity.kt @@ -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 @@ -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), diff --git a/app/src/main/java/ani/dantotsu/settings/SubscriptionItem.kt b/app/src/main/java/ani/dantotsu/settings/SubscriptionItem.kt new file mode 100644 index 00000000..6c6cf941 --- /dev/null +++ b/app/src/main/java/ani/dantotsu/settings/SubscriptionItem.kt @@ -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() { + 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) + } +} \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/settings/SubscriptionsBottomDialog.kt b/app/src/main/java/ani/dantotsu/settings/SubscriptionsBottomDialog.kt new file mode 100644 index 00000000..2b833114 --- /dev/null +++ b/app/src/main/java/ani/dantotsu/settings/SubscriptionsBottomDialog.kt @@ -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 = 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): SubscriptionsBottomDialog { + val dialog = SubscriptionsBottomDialog() + dialog.subscriptions = subscriptions + return dialog + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/settings/saving/PrefManager.kt b/app/src/main/java/ani/dantotsu/settings/saving/PrefManager.kt index 9b3f9293..2a2438d9 100644 --- a/app/src/main/java/ani/dantotsu/settings/saving/PrefManager.kt +++ b/app/src/main/java/ani/dantotsu/settings/saving/PrefManager.kt @@ -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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/animesource/model/SAnime.kt b/app/src/main/java/eu/kanade/tachiyomi/animesource/model/SAnime.kt index 80ee2c4d..2ea0c126 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/animesource/model/SAnime.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/animesource/model/SAnime.kt @@ -85,5 +85,7 @@ interface SAnime : Serializable { fun create(): SAnime { return SAnimeImpl() } + + private const val serialVersionUID = 1L } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/model/SManga.kt b/app/src/main/java/eu/kanade/tachiyomi/source/model/SManga.kt index f0a014e2..232f8982 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/model/SManga.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/model/SManga.kt @@ -84,5 +84,7 @@ interface SManga : Serializable { fun create(): SManga { return SMangaImpl() } + + private const val serialVersionUID = 1L } } diff --git a/app/src/main/res/layout/activity_settings_notifications.xml b/app/src/main/res/layout/activity_settings_notifications.xml index 6aa6f909..a15b9365 100644 --- a/app/src/main/res/layout/activity_settings_notifications.xml +++ b/app/src/main/res/layout/activity_settings_notifications.xml @@ -46,12 +46,12 @@ android:layout_weight="1" android:fontFamily="@font/poppins_bold" android:text="@string/notifications" - android:textSize="28sp" /> + android:textSize="27sp" /> + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 29ede87c..14e4e115 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -991,4 +991,8 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc Replies Open Rules By posting to AniList, you agree to the rules and guidelines of AniList + View Subscriptions + View and edit all your subscriptions + Subscriptions + Subscription Deleted