This commit is contained in:
Luna712 2024-07-11 13:54:43 -06:00 committed by GitHub
parent 8286119062
commit cb21eff44a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 112 additions and 32 deletions

View file

@ -1,6 +1,5 @@
package com.lagradost.cloudstream3.ui.download package com.lagradost.cloudstream3.ui.download
import android.annotation.SuppressLint
import android.text.format.Formatter.formatShortFileSize import android.text.format.Formatter.formatShortFileSize
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
@ -114,7 +113,12 @@ class DownloadAdapter(
} }
} else { } else {
setOnClickListener { setOnClickListener {
onHeaderClickEvent.invoke(DownloadHeaderClickEvent(DOWNLOAD_ACTION_LOAD_RESULT, data)) onHeaderClickEvent.invoke(
DownloadHeaderClickEvent(
DOWNLOAD_ACTION_LOAD_RESULT,
data
)
)
} }
} }
@ -168,7 +172,10 @@ class DownloadAdapter(
} else { } else {
downloadButton.doSetProgress = true downloadButton.doSetProgress = true
downloadButton.progressBar.progressDrawable = downloadButton.progressBar.progressDrawable =
ContextCompat.getDrawable(downloadButton.context, downloadButton.progressDrawable) ContextCompat.getDrawable(
downloadButton.context,
downloadButton.progressDrawable
)
} }
downloadButton.setDefaultClickListener(card.child, downloadHeaderInfo, onItemClickEvent) downloadButton.setDefaultClickListener(card.child, downloadHeaderInfo, onItemClickEvent)
@ -176,12 +183,16 @@ class DownloadAdapter(
if (!isMultiDeleteState) { if (!isMultiDeleteState) {
episodeHolder.setOnClickListener { episodeHolder.setOnClickListener {
onItemClickEvent.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, card.child)) onItemClickEvent.invoke(
DownloadClickEvent(
DOWNLOAD_ACTION_PLAY_FILE,
card.child
)
)
} }
} }
} }
@SuppressLint("SetTextI18n")
private fun DownloadHeaderEpisodeBinding.handleParentDownload( private fun DownloadHeaderEpisodeBinding.handleParentDownload(
card: VisualDownloadCached.Header, card: VisualDownloadCached.Header,
formattedSize: String formattedSize: String
@ -190,19 +201,28 @@ class DownloadAdapter(
downloadHeaderGotoChild.isVisible = !isMultiDeleteState downloadHeaderGotoChild.isVisible = !isMultiDeleteState
try { try {
downloadHeaderInfo.text = downloadHeaderInfo.context.getString(R.string.extra_info_format).format( downloadHeaderInfo.text =
downloadHeaderInfo.context.getString(R.string.extra_info_format).format(
card.totalDownloads, card.totalDownloads,
downloadHeaderInfo.context.resources.getQuantityString(R.plurals.episodes, card.totalDownloads), downloadHeaderInfo.context.resources.getQuantityString(
R.plurals.episodes,
card.totalDownloads
),
formattedSize formattedSize
) )
} catch (e: Exception) { } catch (e: Exception) {
downloadHeaderInfo.text = "Error" downloadHeaderInfo.text = ""
logError(e) logError(e)
} }
if (!isMultiDeleteState) { if (!isMultiDeleteState) {
episodeHolder.setOnClickListener { episodeHolder.setOnClickListener {
onHeaderClickEvent.invoke(DownloadHeaderClickEvent(DOWNLOAD_ACTION_GO_TO_CHILD, card.data)) onHeaderClickEvent.invoke(
DownloadHeaderClickEvent(
DOWNLOAD_ACTION_GO_TO_CHILD,
card.data
)
)
} }
} }
} }
@ -235,14 +255,22 @@ class DownloadAdapter(
downloadButton.progressBar.progressDrawable = downloadButton.progressBar.progressDrawable =
downloadButton.getDrawableFromStatus(status) downloadButton.getDrawableFromStatus(status)
?.let { ContextCompat.getDrawable(downloadButton.context, it) } ?.let { ContextCompat.getDrawable(downloadButton.context, it) }
downloadChildEpisodeTextExtra.text = formatShortFileSize(downloadChildEpisodeTextExtra.context, card.totalBytes) downloadChildEpisodeTextExtra.text =
formatShortFileSize(downloadChildEpisodeTextExtra.context, card.totalBytes)
} else { } else {
downloadButton.doSetProgress = true downloadButton.doSetProgress = true
downloadButton.progressBar.progressDrawable = downloadButton.progressBar.progressDrawable =
ContextCompat.getDrawable(downloadButton.context, downloadButton.progressDrawable) ContextCompat.getDrawable(
downloadButton.context,
downloadButton.progressDrawable
)
} }
downloadButton.setDefaultClickListener(data, downloadChildEpisodeTextExtra, onItemClickEvent) downloadButton.setDefaultClickListener(
data,
downloadChildEpisodeTextExtra,
onItemClickEvent
)
downloadButton.isVisible = !isMultiDeleteState downloadButton.isVisible = !isMultiDeleteState
downloadChildEpisodeText.apply { downloadChildEpisodeText.apply {
@ -261,9 +289,15 @@ class DownloadAdapter(
toggleIsChecked(deleteCheckbox, card) toggleIsChecked(deleteCheckbox, card)
} }
} }
else -> { else -> {
setOnClickListener { setOnClickListener {
onItemClickEvent.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, data)) onItemClickEvent.invoke(
DownloadClickEvent(
DOWNLOAD_ACTION_PLAY_FILE,
data
)
)
} }
} }
} }
@ -311,13 +345,14 @@ class DownloadAdapter(
} }
} }
@SuppressLint("NotifyDataSetChanged")
fun setIsMultiDeleteState(value: Boolean) { fun setIsMultiDeleteState(value: Boolean) {
if (isMultiDeleteState == value) return if (isMultiDeleteState == value) return
isMultiDeleteState = value isMultiDeleteState = value
if (!value) { if (!value) {
selectedIds.clear() selectedIds.clear()
notifyDataSetChanged() currentList.forEachIndexed { index, _ ->
notifyItemChanged(index)
}
} else notifyItemRangeChanged(0, itemCount) } else notifyItemRangeChanged(0, itemCount)
} }
@ -349,11 +384,17 @@ class DownloadAdapter(
} }
class DiffCallback : DiffUtil.ItemCallback<VisualDownloadCached>() { class DiffCallback : DiffUtil.ItemCallback<VisualDownloadCached>() {
override fun areItemsTheSame(oldItem: VisualDownloadCached, newItem: VisualDownloadCached): Boolean { override fun areItemsTheSame(
oldItem: VisualDownloadCached,
newItem: VisualDownloadCached
): Boolean {
return oldItem.data.id == newItem.data.id return oldItem.data.id == newItem.data.id
} }
override fun areContentsTheSame(oldItem: VisualDownloadCached, newItem: VisualDownloadCached): Boolean { override fun areContentsTheSame(
oldItem: VisualDownloadCached,
newItem: VisualDownloadCached
): Boolean {
return oldItem == newItem return oldItem == newItem
} }
} }

View file

@ -30,8 +30,13 @@ object DownloadButtonSetup {
DialogInterface.OnClickListener { _, which -> DialogInterface.OnClickListener { _, which ->
when (which) { when (which) {
DialogInterface.BUTTON_POSITIVE -> { DialogInterface.BUTTON_POSITIVE -> {
VideoDownloadManager.deleteFilesAndUpdateSettings(ctx, listOf(id), MainScope()) VideoDownloadManager.deleteFilesAndUpdateSettings(
ctx,
listOf(id),
MainScope()
)
} }
DialogInterface.BUTTON_NEGATIVE -> { DialogInterface.BUTTON_NEGATIVE -> {
} }
} }
@ -57,11 +62,13 @@ object DownloadButtonSetup {
} }
} }
} }
DOWNLOAD_ACTION_PAUSE_DOWNLOAD -> { DOWNLOAD_ACTION_PAUSE_DOWNLOAD -> {
VideoDownloadManager.downloadEvent.invoke( VideoDownloadManager.downloadEvent.invoke(
Pair(click.data.id, VideoDownloadManager.DownloadActionType.Pause) Pair(click.data.id, VideoDownloadManager.DownloadActionType.Pause)
) )
} }
DOWNLOAD_ACTION_RESUME_DOWNLOAD -> { DOWNLOAD_ACTION_RESUME_DOWNLOAD -> {
activity?.let { ctx -> activity?.let { ctx ->
if (VideoDownloadManager.downloadStatus.containsKey(id) && VideoDownloadManager.downloadStatus[id] == VideoDownloadManager.DownloadType.IsPaused) { if (VideoDownloadManager.downloadStatus.containsKey(id) && VideoDownloadManager.downloadStatus[id] == VideoDownloadManager.DownloadType.IsPaused) {
@ -80,6 +87,7 @@ object DownloadButtonSetup {
} }
} }
} }
DOWNLOAD_ACTION_LONG_CLICK -> { DOWNLOAD_ACTION_LONG_CLICK -> {
activity?.let { act -> activity?.let { act ->
val length = val length =
@ -97,6 +105,7 @@ object DownloadButtonSetup {
} }
} }
} }
DOWNLOAD_ACTION_PLAY_FILE -> { DOWNLOAD_ACTION_PLAY_FILE -> {
activity?.let { act -> activity?.let { act ->
val info = val info =

View file

@ -116,14 +116,32 @@ class DownloadFragment : Fragment() {
binding?.textNoDownloads?.isVisible = it.isEmpty() binding?.textNoDownloads?.isVisible = it.isEmpty()
} }
observe(downloadsViewModel.availableBytes) { observe(downloadsViewModel.availableBytes) {
updateStorageInfo(view.context, it, R.string.free_storage, binding?.downloadFreeTxt, binding?.downloadFree) updateStorageInfo(
view.context,
it,
R.string.free_storage,
binding?.downloadFreeTxt,
binding?.downloadFree
)
} }
observe(downloadsViewModel.usedBytes) { observe(downloadsViewModel.usedBytes) {
updateStorageInfo(view.context, it, R.string.used_storage, binding?.downloadUsedTxt, binding?.downloadUsed) updateStorageInfo(
view.context,
it,
R.string.used_storage,
binding?.downloadUsedTxt,
binding?.downloadUsed
)
binding?.downloadStorageAppbar?.isVisible = it > 0 binding?.downloadStorageAppbar?.isVisible = it > 0
} }
observe(downloadsViewModel.downloadBytes) { observe(downloadsViewModel.downloadBytes) {
updateStorageInfo(view.context, it, R.string.app_storage, binding?.downloadAppTxt, binding?.downloadApp) updateStorageInfo(
view.context,
it,
R.string.app_storage,
binding?.downloadAppTxt,
binding?.downloadApp
)
} }
observe(downloadsViewModel.selectedBytes) { observe(downloadsViewModel.selectedBytes) {
updateDeleteButton(downloadsViewModel.selectedItems.value?.count() ?: 0, it) updateDeleteButton(downloadsViewModel.selectedItems.value?.count() ?: 0, it)
@ -204,13 +222,15 @@ class DownloadFragment : Fragment() {
when (click.action) { when (click.action) {
DOWNLOAD_ACTION_GO_TO_CHILD -> { DOWNLOAD_ACTION_GO_TO_CHILD -> {
if (!click.data.type.isMovieType()) { if (!click.data.type.isMovieType()) {
val folder = DataStore.getFolderName(DOWNLOAD_EPISODE_CACHE, click.data.id.toString()) val folder =
DataStore.getFolderName(DOWNLOAD_EPISODE_CACHE, click.data.id.toString())
activity?.navigate( activity?.navigate(
R.id.action_navigation_downloads_to_navigation_download_child, R.id.action_navigation_downloads_to_navigation_download_child,
DownloadChildFragment.newInstance(click.data.name, folder) DownloadChildFragment.newInstance(click.data.name, folder)
) )
} }
} }
DOWNLOAD_ACTION_LOAD_RESULT -> { DOWNLOAD_ACTION_LOAD_RESULT -> {
(activity as AppCompatActivity?)?.loadResult(click.data.url, click.data.apiName) (activity as AppCompatActivity?)?.loadResult(click.data.url, click.data.apiName)
} }
@ -272,7 +292,10 @@ class DownloadFragment : Fragment() {
textView: TextView?, textView: TextView?,
view: View? view: View?
) { ) {
textView?.text = getString(R.string.storage_size_format).format(getString(stringRes), formatShortFileSize(context, bytes)) textView?.text = getString(R.string.storage_size_format).format(
getString(stringRes),
formatShortFileSize(context, bytes)
)
view?.setLayoutWidth(bytes) view?.setLayoutWidth(bytes)
} }
@ -305,7 +328,9 @@ class DownloadFragment : Fragment() {
if (!preventAutoSwitching) activateSwitchOnHls(text?.toString(), binding) if (!preventAutoSwitching) activateSwitchOnHls(text?.toString(), binding)
} }
(activity?.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager)?.primaryClip?.getItemAt(0)?.text?.toString()?.let { copy -> (activity?.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager)?.primaryClip?.getItemAt(
0
)?.text?.toString()?.let { copy ->
val fixedText = copy.trim() val fixedText = copy.trim()
binding.streamUrl.setText(fixedText) binding.streamUrl.setText(fixedText)
activateSwitchOnHls(fixedText, binding) activateSwitchOnHls(fixedText, binding)

View file

@ -321,16 +321,19 @@ class DownloadViewModel : ViewModel() {
data.seriesNames.isNotEmpty() && data.names.isEmpty() -> { data.seriesNames.isNotEmpty() && data.names.isEmpty() -> {
context.getString(R.string.delete_message_series_only).format(formattedSeriesNames) context.getString(R.string.delete_message_series_only).format(formattedSeriesNames)
} }
data.parentName != null && data.names.isNotEmpty() -> { data.parentName != null && data.names.isNotEmpty() -> {
context.getString(R.string.delete_message_series_episodes) context.getString(R.string.delete_message_series_episodes)
.format(data.parentName, formattedNames) .format(data.parentName, formattedNames)
} }
data.seriesNames.isNotEmpty() -> { data.seriesNames.isNotEmpty() -> {
val seriesSection = context.getString(R.string.delete_message_series_section) val seriesSection = context.getString(R.string.delete_message_series_section)
.format(formattedSeriesNames) .format(formattedSeriesNames)
context.getString(R.string.delete_message_multiple) context.getString(R.string.delete_message_multiple)
.format(formattedNames) + "\n\n" + seriesSection .format(formattedNames) + "\n\n" + seriesSection
} }
else -> context.getString(R.string.delete_message_multiple).format(formattedNames) else -> context.getString(R.string.delete_message_multiple).format(formattedNames)
} }
@ -345,6 +348,7 @@ class DownloadViewModel : ViewModel() {
onDeleteConfirm.invoke() onDeleteConfirm.invoke()
} }
} }
DialogInterface.BUTTON_NEGATIVE -> { DialogInterface.BUTTON_NEGATIVE -> {
// Do nothing on cancel // Do nothing on cancel
} }

View file

@ -92,7 +92,7 @@ abstract class BaseFetchButton(context: Context, attributeSet: AttributeSet) :
abstract fun setStatus(status: VideoDownloadManager.DownloadType?) abstract fun setStatus(status: VideoDownloadManager.DownloadType?)
fun getStatus(id:Int, downloadedBytes: Long, totalBytes: Long): DownloadStatusTell { fun getStatus(id: Int, downloadedBytes: Long, totalBytes: Long): DownloadStatusTell {
// some extra padding for just in case // some extra padding for just in case
return VideoDownloadManager.downloadStatus[id] return VideoDownloadManager.downloadStatus[id]
?: if (downloadedBytes > 1024L && downloadedBytes + 1024L >= totalBytes) { ?: if (downloadedBytes > 1024L && downloadedBytes + 1024L >= totalBytes) {
@ -100,7 +100,7 @@ abstract class BaseFetchButton(context: Context, attributeSet: AttributeSet) :
} else DownloadStatusTell.IsPaused } else DownloadStatusTell.IsPaused
} }
fun applyMetaData(id:Int, downloadedBytes: Long, totalBytes: Long) { fun applyMetaData(id: Int, downloadedBytes: Long, totalBytes: Long) {
val status = getStatus(id, downloadedBytes, totalBytes) val status = getStatus(id, downloadedBytes, totalBytes)
currentMetaData.apply { currentMetaData.apply {
@ -139,7 +139,8 @@ abstract class BaseFetchButton(context: Context, attributeSet: AttributeSet) :
} else { } else {
if (doSetProgress) { if (doSetProgress) {
progressText?.apply { progressText?.apply {
val currentFormattedSizeString = formatShortFileSize(context, downloadedBytes) val currentFormattedSizeString =
formatShortFileSize(context, downloadedBytes)
val totalFormattedSizeString = formatShortFileSize(context, totalBytes) val totalFormattedSizeString = formatShortFileSize(context, totalBytes)
text = text =
// if (isTextPercentage) "%d%%".format(setCurrentBytes * 100L / setTotalBytes) else // if (isTextPercentage) "%d%%".format(setCurrentBytes * 100L / setTotalBytes) else

View file

@ -248,7 +248,7 @@ open class PieFetchButton(context: Context, attributeSet: AttributeSet) :
} */ } */
@MainThread @MainThread
private fun setStatusInternal(status : DownloadStatusTell?) { private fun setStatusInternal(status: DownloadStatusTell?) {
val isPreActive = isZeroBytes && status == DownloadStatusTell.IsDownloading val isPreActive = isZeroBytes && status == DownloadStatusTell.IsDownloading
if (animateWaiting && (status == DownloadStatusTell.IsPending || isPreActive)) { if (animateWaiting && (status == DownloadStatusTell.IsPending || isPreActive)) {
val animation = AnimationUtils.loadAnimation(context, waitingAnimation) val animation = AnimationUtils.loadAnimation(context, waitingAnimation)
@ -286,7 +286,7 @@ open class PieFetchButton(context: Context, attributeSet: AttributeSet) :
if (Looper.myLooper() == Looper.getMainLooper()) { if (Looper.myLooper() == Looper.getMainLooper()) {
try { try {
setStatusInternal(status) setStatusInternal(status)
} catch (t : Throwable) { } catch (t: Throwable) {
logError(t) // Just in case setStatusInternal throws because thread logError(t) // Just in case setStatusInternal throws because thread
progressBarBackground.post { progressBarBackground.post {
setStatusInternal(status) setStatusInternal(status)