verbose downloading

This commit is contained in:
rebelonion 2024-01-16 17:53:46 -06:00
parent 8375cb5c03
commit 84fc5e6e2c
11 changed files with 337 additions and 63 deletions

View file

@ -259,6 +259,7 @@ class MainActivity : AppCompatActivity() {
}
}
}
//TODO: Remove this
GlobalScope.launch(Dispatchers.IO) {
val index = Helper.downloadManager(this@MainActivity).downloadIndex
val downloadCursor = index.getDownloads()

View file

@ -157,6 +157,14 @@ class AnimeDownloaderService : Service() {
val url =
AnimeServiceDataSingleton.downloadQueue.find { it.getTaskName() == taskName }?.video?.file?.url
?: ""
DownloadService.sendSetStopReason(
this@AnimeDownloaderService,
ExoplayerDownloadService::class.java,
url,
androidx.media3.exoplayer.offline.Download.STATE_REMOVING,
false
)
DownloadService.sendRemoveDownload(
this@AnimeDownloaderService,
ExoplayerDownloadService::class.java,
@ -191,7 +199,7 @@ class AnimeDownloaderService : Service() {
}
@androidx.annotation.OptIn(UnstableApi::class)
suspend fun download(task: DownloadTask) {
suspend fun download(task: AnimeDownloadTask) {
try {
val downloadManager = Helper.downloadManager(this@AnimeDownloaderService)
withContext(Dispatchers.Main) {
@ -209,7 +217,7 @@ class AnimeDownloaderService : Service() {
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
broadcastDownloadStarted(task.getTaskName())
broadcastDownloadStarted(task.episode)
currActivity()?.let {
Helper.downloadVideo(
@ -228,7 +236,7 @@ class AnimeDownloaderService : Service() {
builder.setContentText("${task.title} - ${task.episode} Download failed to start")
notificationManager.notify(NOTIFICATION_ID, builder.build())
snackString("${task.title} - ${task.episode} Download failed to start")
broadcastDownloadFailed(task.getTaskName())
broadcastDownloadFailed(task.episode)
return@withContext
}
@ -252,7 +260,7 @@ class AnimeDownloaderService : Service() {
" episode: ${task.episode}"
)
)
broadcastDownloadFailed(task.getTaskName())
broadcastDownloadFailed(task.episode)
break
}
if (download.state == androidx.media3.exoplayer.offline.Download.STATE_COMPLETED) {
@ -274,7 +282,7 @@ class AnimeDownloaderService : Service() {
DownloadedType.Type.ANIME,
)
)
broadcastDownloadFinished(task.getTaskName())
broadcastDownloadFinished(task.episode)
break
}
if (download.state == androidx.media3.exoplayer.offline.Download.STATE_STOPPED) {
@ -285,7 +293,7 @@ class AnimeDownloaderService : Service() {
break
}
broadcastDownloadProgress(
task.getTaskName(),
task.episode,
download.percentDownloaded.toInt()
)
if (notifi) {
@ -299,14 +307,14 @@ class AnimeDownloaderService : Service() {
logger("Exception while downloading file: ${e.message}")
snackString("Exception while downloading file: ${e.message}")
FirebaseCrashlytics.getInstance().recordException(e)
broadcastDownloadFailed(task.getTaskName())
broadcastDownloadFailed(task.episode)
}
}
@androidx.annotation.OptIn(UnstableApi::class)
suspend fun hasDownloadStarted(
downloadManager: DownloadManager,
task: DownloadTask,
task: AnimeDownloadTask,
timeout: Long
): Boolean {
val startTime = System.currentTimeMillis()
@ -322,7 +330,7 @@ class AnimeDownloaderService : Service() {
}
@OptIn(DelicateCoroutinesApi::class)
private fun saveMediaInfo(task: DownloadTask) {
private fun saveMediaInfo(task: AnimeDownloadTask) {
GlobalScope.launch(Dispatchers.IO) {
val directory = File(
getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
@ -406,30 +414,30 @@ class AnimeDownloaderService : Service() {
}
}
private fun broadcastDownloadStarted(chapterNumber: String) {
private fun broadcastDownloadStarted(episodeNumber: String) {
val intent = Intent(AnimeWatchFragment.ACTION_DOWNLOAD_STARTED).apply {
putExtra(AnimeWatchFragment.EXTRA_EPISODE_NUMBER, chapterNumber)
putExtra(AnimeWatchFragment.EXTRA_EPISODE_NUMBER, episodeNumber)
}
sendBroadcast(intent)
}
private fun broadcastDownloadFinished(chapterNumber: String) {
private fun broadcastDownloadFinished(episodeNumber: String) {
val intent = Intent(AnimeWatchFragment.ACTION_DOWNLOAD_FINISHED).apply {
putExtra(AnimeWatchFragment.EXTRA_EPISODE_NUMBER, chapterNumber)
putExtra(AnimeWatchFragment.EXTRA_EPISODE_NUMBER, episodeNumber)
}
sendBroadcast(intent)
}
private fun broadcastDownloadFailed(chapterNumber: String) {
private fun broadcastDownloadFailed(episodeNumber: String) {
val intent = Intent(AnimeWatchFragment.ACTION_DOWNLOAD_FAILED).apply {
putExtra(AnimeWatchFragment.EXTRA_EPISODE_NUMBER, chapterNumber)
putExtra(AnimeWatchFragment.EXTRA_EPISODE_NUMBER, episodeNumber)
}
sendBroadcast(intent)
}
private fun broadcastDownloadProgress(chapterNumber: String, progress: Int) {
private fun broadcastDownloadProgress(episodeNumber: String, progress: Int) {
val intent = Intent(AnimeWatchFragment.ACTION_DOWNLOAD_PROGRESS).apply {
putExtra(AnimeWatchFragment.EXTRA_EPISODE_NUMBER, chapterNumber)
putExtra(AnimeWatchFragment.EXTRA_EPISODE_NUMBER, episodeNumber)
putExtra("progress", progress)
}
sendBroadcast(intent)
@ -448,7 +456,7 @@ class AnimeDownloaderService : Service() {
}
data class DownloadTask(
data class AnimeDownloadTask(
val title: String,
val episode: String,
val video: Video,
@ -461,6 +469,12 @@ class AnimeDownloaderService : Service() {
fun getTaskName(): String {
return "$title - $episode"
}
companion object {
fun getTaskName(title: String, episode: String): String {
return "$title - $episode"
}
}
}
companion object {
@ -473,7 +487,7 @@ class AnimeDownloaderService : Service() {
object AnimeServiceDataSingleton {
var video: Video? = null
var sourceMedia: Media? = null
var downloadQueue: Queue<AnimeDownloaderService.DownloadTask> = ConcurrentLinkedQueue()
var downloadQueue: Queue<AnimeDownloaderService.AnimeDownloadTask> = ConcurrentLinkedQueue()
@Volatile
var isServiceRunning: Boolean = false

View file

@ -230,7 +230,7 @@ object Helper {
}
}
val downloadTask = AnimeDownloaderService.DownloadTask(
val animeDownloadTask = AnimeDownloaderService.AnimeDownloadTask(
title,
episode,
video,
@ -255,7 +255,7 @@ object Helper {
getString(context, R.string.anime_downloads),
Context.MODE_PRIVATE
).getString(
downloadTask.getTaskName(),
animeDownloadTask.getTaskName(),
""
) ?: "",
false
@ -264,7 +264,7 @@ object Helper {
getString(context, R.string.anime_downloads),
Context.MODE_PRIVATE
).edit()
.remove(downloadTask.getTaskName())
.remove(animeDownloadTask.getTaskName())
.apply()
downloadsManger.removeDownload(
DownloadedType(
@ -273,7 +273,7 @@ object Helper {
DownloadedType.Type.ANIME
)
)
AnimeServiceDataSingleton.downloadQueue.offer(downloadTask)
AnimeServiceDataSingleton.downloadQueue.offer(animeDownloadTask)
if (!AnimeServiceDataSingleton.isServiceRunning) {
val intent = Intent(context, AnimeDownloaderService::class.java)
ContextCompat.startForegroundService(context, intent)
@ -283,7 +283,7 @@ object Helper {
.setNegativeButton("No") { _, _ -> }
.show()
} else {
AnimeServiceDataSingleton.downloadQueue.offer(downloadTask)
AnimeServiceDataSingleton.downloadQueue.offer(animeDownloadTask)
if (!AnimeServiceDataSingleton.isServiceRunning) {
val intent = Intent(context, AnimeDownloaderService::class.java)
ContextCompat.startForegroundService(context, intent)

View file

@ -242,7 +242,8 @@ class MediaDetailsViewModel : ViewModel() {
i: String,
manager: FragmentManager,
launch: Boolean = true,
prevEp: String? = null
prevEp: String? = null,
isDownload: Boolean = false
) {
Handler(Looper.getMainLooper()).post {
if (manager.findFragmentByTag("dialog") == null && !manager.isDestroyed) {
@ -254,13 +255,11 @@ class MediaDetailsViewModel : ViewModel() {
}
media.selected = this.loadSelected(media)
val selector =
SelectorDialogFragment.newInstance(media.selected!!.server, launch, prevEp)
SelectorDialogFragment.newInstance(media.selected!!.server, launch, prevEp, isDownload)
selector.show(manager, "dialog")
}
}
}
//Manga
var mangaReadSources: MangaReadSources? = null

View file

@ -2,6 +2,10 @@ package ani.dantotsu.media.anime
import android.annotation.SuppressLint
import android.app.AlertDialog
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import android.os.Parcelable
import android.view.LayoutInflater
@ -9,17 +13,25 @@ import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.Toast
import androidx.annotation.OptIn
import androidx.cardview.widget.CardView
import androidx.core.content.ContextCompat
import androidx.core.math.MathUtils
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.offline.DownloadService
import androidx.recyclerview.widget.ConcatAdapter
import androidx.recyclerview.widget.GridLayoutManager
import androidx.viewpager2.widget.ViewPager2
import ani.dantotsu.*
import ani.dantotsu.databinding.FragmentAnimeWatchBinding
import ani.dantotsu.download.DownloadedType
import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.download.anime.AnimeDownloaderService
import ani.dantotsu.download.video.ExoplayerDownloadService
import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaDetailsActivity
import ani.dantotsu.media.MediaDetailsViewModel
@ -43,6 +55,8 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.launch
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import kotlin.math.ceil
import kotlin.math.max
import kotlin.math.roundToInt
@ -62,6 +76,8 @@ class AnimeWatchFragment : Fragment() {
private lateinit var headerAdapter: AnimeWatchAdapter
private lateinit var episodeAdapter: EpisodeAdapter
val downloadManager = Injekt.get<DownloadsManager>()
var screenWidth = 0f
private var progress = View.VISIBLE
@ -81,6 +97,21 @@ class AnimeWatchFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val intentFilter = IntentFilter().apply {
addAction(ACTION_DOWNLOAD_STARTED)
addAction(ACTION_DOWNLOAD_FINISHED)
addAction(ACTION_DOWNLOAD_FAILED)
addAction(ACTION_DOWNLOAD_PROGRESS)
}
ContextCompat.registerReceiver(
requireContext(),
downloadStatusReceiver,
intentFilter,
ContextCompat.RECEIVER_EXPORTED
)
binding.animeSourceRecycler.updatePadding(bottom = binding.animeSourceRecycler.paddingBottom + navBarHeight)
screenWidth = resources.displayMetrics.widthPixels.dp
@ -135,9 +166,15 @@ class AnimeWatchFragment : Fragment() {
if (!loaded) {
model.watchSources = if (media.isAdult) HAnimeSources else AnimeSources
val offlineMode = model.watchSources!!.list[media.selected!!.sourceIndex].name == "Downloaded"
headerAdapter = AnimeWatchAdapter(it, this, model.watchSources!!)
episodeAdapter =
EpisodeAdapter(style ?: uiSettings.animeDefaultView, media, this)
EpisodeAdapter(style ?: uiSettings.animeDefaultView, media, this, offlineMode = offlineMode)
for (download in downloadManager.animeDownloadedTypes) {
episodeAdapter.stopDownload(download.chapter)
}
binding.animeSourceRecycler.adapter =
ConcatAdapter(headerAdapter, episodeAdapter)
@ -381,6 +418,90 @@ class AnimeWatchFragment : Fragment() {
model.onEpisodeClick(media, i, requireActivity().supportFragmentManager)
}
fun onAnimeEpisodeDownloadClick(i: String) {
model.onEpisodeClick(media, i, requireActivity().supportFragmentManager, isDownload = true)
}
fun onAnimeEpisodeStopDownloadClick(i: String) {
val cancelIntent = Intent().apply {
action = AnimeDownloaderService.ACTION_CANCEL_DOWNLOAD
putExtra(AnimeDownloaderService.EXTRA_TASK_NAME, AnimeDownloaderService.AnimeDownloadTask.getTaskName(media.mainName(), i))
}
requireContext().sendBroadcast(cancelIntent)
// Remove the download from the manager and update the UI
downloadManager.removeDownload(
DownloadedType(
media.mainName(),
i,
DownloadedType.Type.ANIME
)
)
episodeAdapter.purgeDownload(i)
}
@OptIn(UnstableApi::class)
fun onAnimeEpisodeRemoveDownloadClick(i: String) {
downloadManager.removeDownload(
DownloadedType(
media.mainName(),
i,
DownloadedType.Type.ANIME
)
)
val taskName = AnimeDownloaderService.AnimeDownloadTask.getTaskName(media.mainName(), i)
val id = requireContext().getSharedPreferences(
ContextCompat.getString(requireContext(), R.string.anime_downloads),
Context.MODE_PRIVATE
).getString(
taskName,
""
) ?: ""
requireContext().getSharedPreferences(
ContextCompat.getString(requireContext(), R.string.anime_downloads),
Context.MODE_PRIVATE
).edit().remove(taskName).apply()
DownloadService.sendRemoveDownload(
requireContext(),
ExoplayerDownloadService::class.java,
id,
true
)
episodeAdapter.deleteDownload(i)
}
private val downloadStatusReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (!this@AnimeWatchFragment::episodeAdapter.isInitialized) return
when (intent.action) {
ACTION_DOWNLOAD_STARTED -> {
val chapterNumber = intent.getStringExtra(EXTRA_EPISODE_NUMBER)
chapterNumber?.let { episodeAdapter.startDownload(it) }
}
ACTION_DOWNLOAD_FINISHED -> {
val chapterNumber = intent.getStringExtra(EXTRA_EPISODE_NUMBER)
chapterNumber?.let { episodeAdapter.stopDownload(it) }
}
ACTION_DOWNLOAD_FAILED -> {
val chapterNumber = intent.getStringExtra(EXTRA_EPISODE_NUMBER)
chapterNumber?.let {
episodeAdapter.purgeDownload(it)
}
}
ACTION_DOWNLOAD_PROGRESS -> {
val chapterNumber = intent.getStringExtra(EXTRA_EPISODE_NUMBER)
val progress = intent.getIntExtra("progress", 0)
chapterNumber?.let {
episodeAdapter.updateDownloadProgress(it, progress)
}
}
}
}
}
@SuppressLint("NotifyDataSetChanged")
private fun reload() {
val selected = model.loadSelected(media)
@ -393,6 +514,8 @@ class AnimeWatchFragment : Fragment() {
model.saveSelected(media.id, selected, requireActivity())
headerAdapter.handleEpisodes()
val isDownloaded = model.watchSources?.list?.get(selected.sourceIndex)?.name == "Downloaded"
episodeAdapter.offlineMode = isDownloaded
episodeAdapter.notifyItemRangeRemoved(0, episodeAdapter.arr.size)
var arr: ArrayList<Episode> = arrayListOf()
if (media.anime!!.episodes != null) {
@ -412,6 +535,7 @@ class AnimeWatchFragment : Fragment() {
override fun onDestroy() {
model.watchSources?.flushText()
super.onDestroy()
requireContext().unregisterReceiver(downloadStatusReceiver)
}
var state: Parcelable? = null

View file

@ -14,6 +14,7 @@ data class Episode(
var selectedExtractor: String? = null,
var selectedVideo: Int = 0,
var selectedSubtitle: Int? = -1,
var downloadProgress: String? = null,
@Transient var extractors: MutableList<VideoExtractor>? = null,
@Transient var extractorCallback: ((VideoExtractor) -> Unit)? = null,
var allStreams: Boolean = false,

View file

@ -4,7 +4,10 @@ import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.LinearInterpolator
import android.widget.LinearLayout
import androidx.lifecycle.coroutineScope
import androidx.media3.exoplayer.offline.Download
import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.*
import ani.dantotsu.connections.updateProgress
@ -14,6 +17,8 @@ import ani.dantotsu.databinding.ItemEpisodeListBinding
import ani.dantotsu.media.Media
import com.bumptech.glide.Glide
import com.bumptech.glide.load.model.GlideUrl
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
fun handleProgress(cont: LinearLayout, bar: View, empty: View, mediaId: Int, ep: String) {
val curr = loadData<Long>("${mediaId}_${ep}")
@ -36,7 +41,8 @@ class EpisodeAdapter(
private var type: Int,
private val media: Media,
private val fragment: AnimeWatchFragment,
var arr: List<Episode> = arrayListOf()
var arr: List<Episode> = arrayListOf(),
var offlineMode: Boolean
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
@ -101,6 +107,7 @@ class EpisodeAdapter(
binding.itemEpisodeFiller.visibility = View.GONE
binding.itemEpisodeFillerView.visibility = View.GONE
}
holder.bind(ep.number, ep.downloadProgress)
binding.itemEpisodeDesc.visibility =
if (ep.desc != null && ep.desc?.trim(' ') != "") View.VISIBLE else View.GONE
binding.itemEpisodeDesc.text = ep.desc ?: ""
@ -204,6 +211,61 @@ class EpisodeAdapter(
override fun getItemCount(): Int = arr.size
private val activeDownloads = mutableSetOf<String>()
private val downloadedEpisodes = mutableSetOf<String>()
fun startDownload(episodeNumber: String) {
activeDownloads.add(episodeNumber)
// Find the position of the chapter and notify only that item
val position = arr.indexOfFirst { it.number == episodeNumber }
if (position != -1) {
notifyItemChanged(position)
}
}
fun stopDownload(episodeNumber: String) {
activeDownloads.remove(episodeNumber)
downloadedEpisodes.add(episodeNumber)
// Find the position of the chapter and notify only that item
val position = arr.indexOfFirst { it.number == episodeNumber }
if (position != -1) {
arr[position].downloadProgress = "Downloaded"
notifyItemChanged(position)
}
}
fun deleteDownload(episodeNumber: String) {
downloadedEpisodes.remove(episodeNumber)
// Find the position of the chapter and notify only that item
val position = arr.indexOfFirst { it.number == episodeNumber }
if (position != -1) {
arr[position].downloadProgress = null
notifyItemChanged(position)
}
}
fun purgeDownload(episodeNumber: String) {
activeDownloads.remove(episodeNumber)
downloadedEpisodes.remove(episodeNumber)
// Find the position of the chapter and notify only that item
val position = arr.indexOfFirst { it.number == episodeNumber }
if (position != -1) {
arr[position].downloadProgress = "Failed"
notifyItemChanged(position)
}
}
fun updateDownloadProgress(episodeNumber: String, progress: Int) {
// Find the position of the chapter and notify only that item
val position = arr.indexOfFirst { it.number == episodeNumber }
if (position != -1) {
arr[position].downloadProgress = "Downloading: $progress%"
notifyItemChanged(position)
}
}
inner class EpisodeCompactViewHolder(val binding: ItemEpisodeCompactBinding) :
RecyclerView.ViewHolder(binding.root) {
init {
@ -226,11 +288,26 @@ class EpisodeAdapter(
inner class EpisodeListViewHolder(val binding: ItemEpisodeListBinding) :
RecyclerView.ViewHolder(binding.root) {
private val activeCoroutines = mutableSetOf<String>()
init {
itemView.setOnClickListener {
if (bindingAdapterPosition < arr.size && bindingAdapterPosition >= 0)
fragment.onEpisodeClick(arr[bindingAdapterPosition].number)
}
binding.itemDownload.setOnClickListener {
if (0 <= bindingAdapterPosition && bindingAdapterPosition < arr.size) {
val episodeNumber = arr[bindingAdapterPosition].number
if (activeDownloads.contains(episodeNumber)) {
fragment.onAnimeEpisodeStopDownloadClick(episodeNumber)
return@setOnClickListener
} else if (downloadedEpisodes.contains(episodeNumber)) {
fragment.onAnimeEpisodeRemoveDownloadClick(episodeNumber)
return@setOnClickListener
} else {
fragment.onAnimeEpisodeDownloadClick(episodeNumber)
}
}
}
binding.itemEpisodeDesc.setOnClickListener {
if (binding.itemEpisodeDesc.maxLines == 3)
binding.itemEpisodeDesc.maxLines = 100
@ -238,6 +315,57 @@ class EpisodeAdapter(
binding.itemEpisodeDesc.maxLines = 3
}
}
fun bind(episodeNumber: String, progress: String?) {
if (progress != null) {
binding.itemDownloadStatus.visibility = View.VISIBLE
binding.itemDownloadStatus.text = "$progress"
} else {
binding.itemDownloadStatus.visibility = View.GONE
binding.itemDownloadStatus.text = ""
}
if (activeDownloads.contains(episodeNumber)) {
// Show spinner
binding.itemDownload.setImageResource(R.drawable.ic_sync)
startOrContinueRotation(episodeNumber)
} else if (downloadedEpisodes.contains(episodeNumber)) {
// Show checkmark
binding.itemDownload.setImageResource(R.drawable.ic_circle_check)
//binding.itemDownload.setColorFilter(typedValue2.data) //TODO: colors go to wrong places
binding.itemDownload.postDelayed({
binding.itemDownload.setImageResource(R.drawable.ic_round_delete_24)
binding.itemDownload.rotation = 0f
//binding.itemDownload.setColorFilter(typedValue2.data)
}, 1000)
} else {
// Show download icon
binding.itemDownload.setImageResource(R.drawable.ic_circle_add)
}
}
private fun startOrContinueRotation(episodeNumber: String) {
if (!isRotationCoroutineRunningFor(episodeNumber)) {
val scope = fragment.lifecycle.coroutineScope
scope.launch {
// Add chapter number to active coroutines set
activeCoroutines.add(episodeNumber)
while (activeDownloads.contains(episodeNumber)) {
binding.itemDownload.animate().rotationBy(360f).setDuration(1000)
.setInterpolator(
LinearInterpolator()
).start()
delay(1000)
}
// Remove chapter number from active coroutines set
activeCoroutines.remove(episodeNumber)
}
}
}
private fun isRotationCoroutineRunningFor(episodeNumber: String): Boolean {
return episodeNumber in activeCoroutines
}
}
fun updateType(t: Int) {

View file

@ -1328,18 +1328,6 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
ext.onVideoPlayed(video)
}
val but = playerView.findViewById<ImageButton>(R.id.exo_download)
if (video?.format == VideoType.CONTAINER || (loadData<Int>("settings_download_manager")
?: 0) != 0
) {
//but.visibility = View.VISIBLE TODO: not sure if this is needed
but.setOnClickListener {
download(this, episode, animeTitle.text.toString())
}
} else {
but.visibility = View.GONE
}
val simpleCache = VideoCache.getInstance(this)
val httpClient = okHttpClient.newBuilder().apply {
ignoreAllSSLErrors()

View file

@ -43,6 +43,7 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
private var makeDefault = false
private var selected: String? = null
private var launch: Boolean? = null
private var isDownload: Boolean? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -50,6 +51,7 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
selected = it.getString("server")
launch = it.getBoolean("launch", true)
prevEpisode = it.getString("prev")
isDownload = it.getBoolean("isDownload")
}
}
@ -77,8 +79,10 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
val ep = media?.anime?.episodes?.get(media?.anime?.selectedEpisode)
episode = ep
if (ep != null) {
if (selected != null) {
if (isDownload == true) {
binding.selectorMakeDefault.visibility = View.GONE
}
if (selected != null && isDownload == false) {
binding.selectorListContainer.visibility = View.GONE
binding.selectorAutoListContainer.visibility = View.VISIBLE
binding.selectorAutoText.text = selected
@ -258,11 +262,11 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
override fun onBindViewHolder(holder: UrlViewHolder, position: Int) {
val binding = holder.binding
val video = extractor.videos[position]
//binding.urlQuality.text =
// if (video.quality != null) "${video.quality}p" else "Default Quality"
//binding.urlNote.text = video.extraNote ?: ""
//binding.urlNote.visibility = if (video.extraNote != null) View.VISIBLE else View.GONE
if (isDownload == true) {
binding.urlDownload.visibility = View.VISIBLE
} else {
binding.urlDownload.visibility = View.GONE
}
binding.urlDownload.setSafeOnClickListener {
media!!.anime!!.episodes!![media!!.anime!!.selectedEpisode!!]!!.selectedExtractor =
extractor.server.name
@ -314,6 +318,10 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
RecyclerView.ViewHolder(binding.root) {
init {
itemView.setSafeOnClickListener {
if (isDownload == true) {
binding.urlDownload.performClick()
return@setSafeOnClickListener
}
tryWith(true) {
media!!.anime!!.episodes!![media!!.anime!!.selectedEpisode!!]?.selectedExtractor =
extractor.server.name
@ -345,13 +353,15 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
fun newInstance(
server: String? = null,
la: Boolean = true,
prev: String? = null
prev: String? = null,
isDownload: Boolean
): SelectorDialogFragment =
SelectorDialogFragment().apply {
arguments = Bundle().apply {
putString("server", server)
putBoolean("launch", la)
putString("prev", prev)
putBoolean("isDownload", isDownload)
}
}
}

View file

@ -148,18 +148,6 @@
app:tint="#fff"
tools:ignore="ContentDescription,SpeakableTextPresentCheck" />
<ImageButton
android:id="@+id/exo_download"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:backgroundTint="#00FFFFFF"
android:src="@drawable/ic_round_download_24"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:tint="#fff"
tools:ignore="ContentDescription,SpeakableTextPresentCheck" />
<View
android:layout_width="0dp"
android:layout_height="match_parent"

View file

@ -101,9 +101,10 @@
</androidx.cardview.widget.CardView>
<LinearLayout
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="1"
android:gravity="center"
android:minHeight="92dp"
android:orientation="vertical">
@ -130,8 +131,28 @@
android:text="@string/empty"
app:lineHeight="15sp" />
<TextView
android:id="@+id/itemDownloadStatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:fontFamily="@font/poppins_bold"
android:maxLines="5"
android:visibility="gone"
android:text=""
app:lineHeight="15sp" />
</LinearLayout>
<ImageButton
android:id="@+id/itemDownload"
android:layout_width="24dp"
android:layout_height="48dp"
android:layout_marginEnd="8dp"
android:background="?android:attr/selectableItemBackground"
app:tint="?attr/colorOnBackground"
app:srcCompat="@drawable/ic_round_download_24" />
</LinearLayout>
<TextView