downloading button cleanup

This commit is contained in:
Finnley Somdahl 2023-11-21 20:34:34 -06:00
parent c310bea0e9
commit 84c58fbe6c
12 changed files with 108 additions and 26 deletions

View file

@ -21,7 +21,7 @@ android {
minSdk 23 minSdk 23
targetSdk 34 targetSdk 34
versionCode ((System.currentTimeMillis() / 60000).toInteger()) versionCode ((System.currentTimeMillis() / 60000).toInteger())
versionName "1.0.0-beta02" versionName "1.0.0-beta03i"
signingConfig signingConfigs.debug signingConfig signingConfigs.debug
} }

View file

@ -9,6 +9,7 @@
android:name="android.hardware.touchscreen" android:name="android.hardware.touchscreen"
android:required="false" /> android:required="false" />
<uses-permission android:name="android.permissionandroid.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

View file

@ -32,6 +32,7 @@ import ani.dantotsu.navBarHeight
import ani.dantotsu.px import ani.dantotsu.px
import ani.dantotsu.setSafeOnClickListener import ani.dantotsu.setSafeOnClickListener
import ani.dantotsu.settings.SettingsDialogFragment import ani.dantotsu.settings.SettingsDialogFragment
import ani.dantotsu.snackString
import ani.dantotsu.statusBarHeight import ani.dantotsu.statusBarHeight
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.imageview.ShapeableImageView import com.google.android.material.imageview.ShapeableImageView
@ -84,12 +85,16 @@ class OfflineMangaFragment: Fragment() {
gridView.setOnItemClickListener { parent, view, position, id -> gridView.setOnItemClickListener { parent, view, position, id ->
// Get the OfflineMangaModel that was clicked // Get the OfflineMangaModel that was clicked
val item = adapter.getItem(position) as OfflineMangaModel val item = adapter.getItem(position) as OfflineMangaModel
val media = downloadManager.mangaDownloads.filter { it.title == item.title }.first() val media = downloadManager.mangaDownloads.filter { it.title == item.title }.firstOrNull()
startActivity( media?.let {
Intent(requireContext(), MediaDetailsActivity::class.java) startActivity(
.putExtra("media", getMedia(media)) Intent(requireContext(), MediaDetailsActivity::class.java)
.putExtra("download", true) .putExtra("media", getMedia(it))
) .putExtra("download", true)
)
} ?: run {
snackString("no media found")
}
} }
return view return view

View file

@ -1,8 +1,12 @@
package ani.dantotsu.media.manga package ani.dantotsu.media.manga
import android.util.TypedValue
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.animation.LinearInterpolator
import androidx.core.content.ContentProviderCompat.requireContext
import androidx.lifecycle.coroutineScope
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.databinding.ItemChapterListBinding import ani.dantotsu.databinding.ItemChapterListBinding
@ -10,8 +14,9 @@ import ani.dantotsu.databinding.ItemEpisodeCompactBinding
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.setAnimation import ani.dantotsu.setAnimation
import ani.dantotsu.connections.updateProgress import ani.dantotsu.connections.updateProgress
import java.util.regex.Matcher import ani.dantotsu.currContext
import java.util.regex.Pattern import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class MangaChapterAdapter( class MangaChapterAdapter(
private var type: Int, private var type: Int,
@ -90,7 +95,7 @@ class MangaChapterAdapter(
} }
} }
fun removeDownload(chapterNumber: String) { fun purgeDownload(chapterNumber: String) {
activeDownloads.remove(chapterNumber) activeDownloads.remove(chapterNumber)
downloadedChapters.remove(chapterNumber) downloadedChapters.remove(chapterNumber)
// Find the position of the chapter and notify only that item // Find the position of the chapter and notify only that item
@ -112,6 +117,9 @@ class MangaChapterAdapter(
inner class ChapterListViewHolder(val binding: ItemChapterListBinding) : inner class ChapterListViewHolder(val binding: ItemChapterListBinding) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
private val activeCoroutines = mutableSetOf<String>()
val typedValue1 = TypedValue()
val typedValue2 = TypedValue()
fun bind(chapterNumber: String, progress: String?) { fun bind(chapterNumber: String, progress: String?) {
if (progress != null) { if (progress != null) {
binding.itemChapterTitle.visibility = View.VISIBLE binding.itemChapterTitle.visibility = View.VISIBLE
@ -122,18 +130,49 @@ class MangaChapterAdapter(
} }
if (activeDownloads.contains(chapterNumber)) { if (activeDownloads.contains(chapterNumber)) {
// Show spinner // Show spinner
binding.itemDownload.setImageResource(R.drawable.ic_round_refresh_24) binding.itemDownload.setImageResource(R.drawable.ic_sync)
startOrContinueRotation(chapterNumber)
} else if (downloadedChapters.contains(chapterNumber)) { } else if (downloadedChapters.contains(chapterNumber)) {
// Show checkmark // Show checkmark
binding.itemDownload.setImageResource(R.drawable.ic_check) binding.itemDownload.setImageResource(R.drawable.ic_circle_check)
binding.itemDownload.setColorFilter(typedValue2.data)
binding.itemDownload.postDelayed({
binding.itemDownload.setImageResource(R.drawable.ic_circle_cancel)
binding.itemDownload.setColorFilter(typedValue2.data)
}, 5000)
} else { } else {
// Show download icon // Show download icon
binding.itemDownload.setImageResource(R.drawable.ic_round_download_24) binding.itemDownload.setImageResource(R.drawable.ic_circle_add)
} }
} }
private fun startOrContinueRotation(chapterNumber: String) {
if (!isRotationCoroutineRunningFor(chapterNumber)) {
val scope = fragment.lifecycle.coroutineScope
scope.launch {
// Add chapter number to active coroutines set
activeCoroutines.add(chapterNumber)
while (activeDownloads.contains(chapterNumber)) {
binding.itemDownload.animate().rotationBy(360f).setDuration(1000).setInterpolator(
LinearInterpolator()
).start()
delay(1000)
}
// Remove chapter number from active coroutines set
activeCoroutines.remove(chapterNumber)
}
}
}
private fun isRotationCoroutineRunningFor(chapterNumber: String): Boolean {
return chapterNumber in activeCoroutines
}
init { init {
val theme = currContext()?.theme
theme?.resolveAttribute(com.google.android.material.R.attr.colorError, typedValue1, true)
theme?.resolveAttribute(com.google.android.material.R.attr.colorPrimary, typedValue2, true)
itemView.setOnClickListener { itemView.setOnClickListener {
if (0 <= bindingAdapterPosition && bindingAdapterPosition < arr.size) if (0 <= bindingAdapterPosition && bindingAdapterPosition < arr.size)
fragment.onMangaChapterClick(arr[bindingAdapterPosition].number) fragment.onMangaChapterClick(arr[bindingAdapterPosition].number)

View file

@ -2,7 +2,6 @@ package ani.dantotsu.media.manga
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.AlertDialog import android.app.AlertDialog
import android.app.DownloadManager
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
@ -16,7 +15,6 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.Toast import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.cardview.widget.CardView import androidx.cardview.widget.CardView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.math.MathUtils.clamp import androidx.core.math.MathUtils.clamp
@ -42,7 +40,6 @@ import ani.dantotsu.parsers.HMangaSources
import ani.dantotsu.parsers.MangaParser import ani.dantotsu.parsers.MangaParser
import ani.dantotsu.parsers.MangaSources import ani.dantotsu.parsers.MangaSources
import ani.dantotsu.settings.UserInterfaceSettings import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment
import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment
import ani.dantotsu.subcriptions.Notifications import ani.dantotsu.subcriptions.Notifications
import ani.dantotsu.subcriptions.Notifications.Group.MANGA_GROUP import ani.dantotsu.subcriptions.Notifications.Group.MANGA_GROUP
@ -51,8 +48,6 @@ import ani.dantotsu.subcriptions.SubscriptionHelper
import ani.dantotsu.subcriptions.SubscriptionHelper.Companion.saveSubscription import ani.dantotsu.subcriptions.SubscriptionHelper.Companion.saveSubscription
import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.navigationrail.NavigationRailView import com.google.android.material.navigationrail.NavigationRailView
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.ConfigurableSource
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -405,7 +400,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
// Create a download task // Create a download task
val downloadTask = MangaDownloaderService.DownloadTask( val downloadTask = MangaDownloaderService.DownloadTask(
title = media.nameMAL ?: "", title = media.nameMAL ?: media.nameRomaji,
chapter = chapter.title!!, chapter = chapter.title!!,
imageData = images, imageData = images,
sourceMedia = media, sourceMedia = media,
@ -445,7 +440,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
fun onMangaChapterRemoveDownloadClick(i: String){ fun onMangaChapterRemoveDownloadClick(i: String){
downloadManager.removeDownload(Download(media.nameMAL!!, i, Download.Type.MANGA)) downloadManager.removeDownload(Download(media.nameMAL?:media.nameRomaji, i, Download.Type.MANGA))
chapterAdapter.deleteDownload(i) chapterAdapter.deleteDownload(i)
} }
fun onMangaChapterStopDownloadClick(i: String) { fun onMangaChapterStopDownloadClick(i: String) {
@ -456,8 +451,8 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
requireContext().sendBroadcast(cancelIntent) requireContext().sendBroadcast(cancelIntent)
// Remove the download from the manager and update the UI // Remove the download from the manager and update the UI
downloadManager.removeDownload(Download(media.nameMAL!!, i, Download.Type.MANGA)) downloadManager.removeDownload(Download(media.nameMAL?:media.nameRomaji, i, Download.Type.MANGA))
chapterAdapter.stopDownload(i) chapterAdapter.purgeDownload(i)
} }
private val downloadStatusReceiver = object : BroadcastReceiver() { private val downloadStatusReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
@ -473,7 +468,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
ACTION_DOWNLOAD_FAILED -> { ACTION_DOWNLOAD_FAILED -> {
val chapterNumber = intent.getStringExtra(EXTRA_CHAPTER_NUMBER) val chapterNumber = intent.getStringExtra(EXTRA_CHAPTER_NUMBER)
chapterNumber?.let { chapterNumber?.let {
chapterAdapter.removeDownload(it) chapterAdapter.purgeDownload(it)
} }
} }
ACTION_DOWNLOAD_PROGRESS -> { ACTION_DOWNLOAD_PROGRESS -> {

View file

@ -47,7 +47,7 @@ class ChapterLoaderDialog : BottomSheetDialogFragment() {
loaded = true loaded = true
binding.selectorAutoText.text = chp.title binding.selectorAutoText.text = chp.title
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
if(model.loadMangaChapterImages(chp, m.selected!!, m.nameMAL!!)) { if(model.loadMangaChapterImages(chp, m.selected!!, m.nameMAL?:m.nameRomaji)) {
val activity = currActivity() val activity = currActivity()
activity?.runOnUiThread { activity?.runOnUiThread {
tryWith { dismiss() } tryWith { dismiss() }

View file

@ -317,7 +317,7 @@ ThemeManager(this).applyTheme()
} }
} }
scope.launch(Dispatchers.IO) { model.loadMangaChapterImages(chapter, media.selected!!, media.nameMAL!!) } scope.launch(Dispatchers.IO) { model.loadMangaChapterImages(chapter, media.selected!!, media.nameMAL?:media.nameRomaji) }
} }
private val snapHelper = PagerSnapHelper() private val snapHelper = PagerSnapHelper()
@ -706,7 +706,7 @@ ThemeManager(this).applyTheme()
model.loadMangaChapterImages( model.loadMangaChapterImages(
chapters[chaptersArr.getOrNull(currentChapterIndex + 1) ?: return@launch]!!, chapters[chaptersArr.getOrNull(currentChapterIndex + 1) ?: return@launch]!!,
media.selected!!, media.selected!!,
media.nameMAL!!, media.nameMAL?:media.nameRomaji,
false false
) )
loading = false loading = false

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M440,680h80v-160h160v-80L520,440v-160h-80v160L280,440v80h160v160ZM480,880q-83,0 -156,-31.5T197,763q-54,-54 -85.5,-127T80,480q0,-83 31.5,-156T197,197q54,-54 127,-85.5T480,80q83,0 156,31.5T763,197q54,54 85.5,127T880,480q0,83 -31.5,156T763,763q-54,54 -127,85.5T480,880ZM480,800q134,0 227,-93t93,-227q0,-134 -93,-227t-227,-93q-134,0 -227,93t-93,227q0,134 93,227t227,93ZM480,480Z"/>
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="m336,680 l144,-144 144,144 56,-56 -144,-144 144,-144 -56,-56 -144,144 -144,-144 -56,56 144,144 -144,144 56,56ZM480,880q-83,0 -156,-31.5T197,763q-54,-54 -85.5,-127T80,480q0,-83 31.5,-156T197,197q54,-54 127,-85.5T480,80q83,0 156,31.5T763,197q54,54 85.5,127T880,480q0,83 -31.5,156T763,763q-54,54 -127,85.5T480,880ZM480,800q134,0 227,-93t93,-227q0,-134 -93,-227t-227,-93q-134,0 -227,93t-93,227q0,134 93,227t227,93ZM480,480Z"/>
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="m424,664 l282,-282 -56,-56 -226,226 -114,-114 -56,56 170,170ZM480,880q-83,0 -156,-31.5T197,763q-54,-54 -85.5,-127T80,480q0,-83 31.5,-156T197,197q54,-54 127,-85.5T480,80q83,0 156,31.5T763,197q54,54 85.5,127T880,480q0,83 -31.5,156T763,763q-54,54 -127,85.5T480,880ZM480,800q134,0 227,-93t93,-227q0,-134 -93,-227t-227,-93q-134,0 -227,93t-93,227q0,134 93,227t227,93ZM480,480Z"/>
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M160,800v-80h110l-16,-14q-52,-46 -73,-105t-21,-119q0,-111 66.5,-197.5T400,170v84q-72,26 -116,88.5T240,482q0,45 17,87.5t53,78.5l10,10v-98h80v240L160,800ZM560,790v-84q72,-26 116,-88.5T720,478q0,-45 -17,-87.5T650,312l-10,-10v98h-80v-240h240v80L690,240l16,14q49,49 71.5,106.5T800,478q0,111 -66.5,197.5T560,790Z"/>
</vector>

View file

@ -97,6 +97,8 @@
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1" android:layout_weight="1"
android:numColumns="auto_fit" android:numColumns="auto_fit"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:columnWidth="108dp" android:columnWidth="108dp"
android:verticalSpacing="10dp" android:verticalSpacing="10dp"
android:horizontalSpacing="10dp" android:horizontalSpacing="10dp"