Merry Fucking Christmas

This commit is contained in:
LagradOst 2021-12-24 17:09:01 +01:00
parent dce2fad64f
commit 989790d5c4
4 changed files with 838 additions and 162 deletions

View file

@ -1,5 +1,6 @@
package com.lagradost.cloudstream3.ui.download
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -9,6 +10,7 @@ import androidx.cardview.widget.CardView
import androidx.core.widget.ContentLoadingProgressBar
import androidx.recyclerview.widget.RecyclerView
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.utils.UIHelper.setImage
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
import kotlinx.android.synthetic.main.download_header_episode.view.*
@ -100,6 +102,7 @@ class DownloadHeaderAdapter(
private val normalImage: ImageView = itemView.download_header_goto_child
private var localCard: VisualDownloadHeaderCached? = null
@SuppressLint("SetTextI18n")
fun bind(card: VisualDownloadHeaderCached) {
localCard = card
val d = card.data
@ -135,14 +138,21 @@ class DownloadHeaderAdapter(
downloadImage.visibility = View.GONE
normalImage.visibility = View.VISIBLE
extraInfo.text =
extraInfo.context.getString(R.string.extra_info_format).format(
card.totalDownloads,
if (card.totalDownloads == 1) extraInfo.context.getString(R.string.episode) else extraInfo.context.getString(
R.string.episodes
),
mbString
)
try {
extraInfo.text =
extraInfo.context.getString(R.string.extra_info_format).format(
card.totalDownloads,
if (card.totalDownloads == 1) extraInfo.context.getString(R.string.episode) else extraInfo.context.getString(
R.string.episodes
),
mbString
)
} catch (e : Exception) {
// you probably formatted incorrectly
extraInfo.text = "Error"
logError(e)
}
holder.setOnClickListener {
clickCallback.invoke(DownloadHeaderClickEvent(0, d))

View file

@ -14,6 +14,7 @@ import com.lagradost.cloudstream3.HomePageResponse
import com.lagradost.cloudstream3.MainAPI
import com.lagradost.cloudstream3.SearchResponse
import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.ui.APIRepository
import com.lagradost.cloudstream3.ui.APIRepository.Companion.noneApi
import com.lagradost.cloudstream3.ui.APIRepository.Companion.randomApi
@ -157,18 +158,23 @@ class HomeViewModel : ViewModel() {
val data = repo?.getMainPage()
when (data) {
is Resource.Success -> {
val home = data.value
if (home?.items?.isNullOrEmpty() == false) {
val currentList =
home.items.shuffled().filter { !it.list.isNullOrEmpty() }.flatMap { it.list }
.distinctBy { it.url }
.toList()
try {
val home = data.value
if (home?.items?.isNullOrEmpty() == false) {
val currentList =
home.items.shuffled().filter { !it.list.isNullOrEmpty() }.flatMap { it.list }
.distinctBy { it.url }
.toList()
if (!currentList.isNullOrEmpty()) {
val randomItems = currentList.shuffled()
if (!currentList.isNullOrEmpty()) {
val randomItems = currentList.shuffled()
_randomItems.postValue(randomItems)
_randomItems.postValue(randomItems)
}
}
} catch (e : Exception) {
_randomItems.postValue(emptyList())
logError(e)
}
}
else -> {

View file

@ -151,14 +151,18 @@ object VideoDownloadManager {
private const val SUCCESS_DOWNLOAD_DONE = 1
private const val SUCCESS_STREAM = 3
private const val SUCCESS_STOPPED = 2
// will not download the next one, but is still classified as an error
private const val ERROR_DELETING_FILE = 3
private const val ERROR_CREATE_FILE = -2
private const val ERROR_UNKNOWN = -10
//private const val ERROR_OPEN_FILE = -3
private const val ERROR_TOO_SMALL_CONNECTION = -4
//private const val ERROR_WRONG_CONTENT = -5
private const val ERROR_CONNECTION_ERROR = -6
//private const val ERROR_MEDIA_STORE_URI_CANT_BE_CREATED = -7
//private const val ERROR_CONTENT_RESOLVER_CANT_OPEN_STREAM = -8
private const val ERROR_CONTENT_RESOLVER_NOT_FOUND = -9
@ -235,73 +239,88 @@ object VideoDownloadManager {
notificationCallback: (Int, Notification) -> Unit
): Notification? {
if (total <= 0) return null// crash, invalid data
try {
if (total <= 0) return null// crash, invalid data
// main { // DON'T WANT TO SLOW IT DOWN
val builder = NotificationCompat.Builder(context, DOWNLOAD_CHANNEL_ID)
.setAutoCancel(true)
.setColorized(true)
.setOnlyAlertOnce(true)
.setShowWhen(false)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setColor(context.colorFromAttribute(R.attr.colorPrimary))
.setContentTitle(ep.mainName)
.setSmallIcon(
when (state) {
DownloadType.IsDone -> imgDone
DownloadType.IsDownloading -> imgDownloading
DownloadType.IsPaused -> imgPaused
DownloadType.IsFailed -> imgError
DownloadType.IsStopped -> imgStopped
}
)
val builder = NotificationCompat.Builder(context, DOWNLOAD_CHANNEL_ID)
.setAutoCancel(true)
.setColorized(true)
.setOnlyAlertOnce(true)
.setShowWhen(false)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setColor(context.colorFromAttribute(R.attr.colorPrimary))
.setContentTitle(ep.mainName)
.setSmallIcon(
when (state) {
DownloadType.IsDone -> imgDone
DownloadType.IsDownloading -> imgDownloading
DownloadType.IsPaused -> imgPaused
DownloadType.IsFailed -> imgError
DownloadType.IsStopped -> imgStopped
}
)
if (ep.sourceApiName != null) {
builder.setSubText(ep.sourceApiName)
}
if (source != null) {
val intent = Intent(context, MainActivity::class.java).apply {
data = source.toUri()
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
if (ep.sourceApiName != null) {
builder.setSubText(ep.sourceApiName)
}
val pendingIntent: PendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
if (source != null) {
val intent = Intent(context, MainActivity::class.java).apply {
data = source.toUri()
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
} else {
PendingIntent.getActivity(context, 0, intent, 0)
}
builder.setContentIntent(pendingIntent)
}
if (state == DownloadType.IsDownloading || state == DownloadType.IsPaused) {
builder.setProgress((total / 1000).toInt(), (progress / 1000).toInt(), false)
}
val rowTwoExtra = if (ep.name != null) " - ${ep.name}\n" else ""
val rowTwo = if (ep.season != null && ep.episode != null) {
"${context.getString(R.string.season_short)}${ep.season}:${context.getString(R.string.episode_short)}${ep.episode}" + rowTwoExtra
} else if (ep.episode != null) {
"${context.getString(R.string.episode)} ${ep.episode}" + rowTwoExtra
} else {
PendingIntent.getActivity(context, 0, intent, 0)
(ep.name ?: "") + ""
}
builder.setContentIntent(pendingIntent)
}
val downloadFormat = context.getString(R.string.download_format)
if (state == DownloadType.IsDownloading || state == DownloadType.IsPaused) {
builder.setProgress((total / 1000).toInt(), (progress / 1000).toInt(), false)
}
val rowTwoExtra = if (ep.name != null) " - ${ep.name}\n" else ""
val rowTwo = if (ep.season != null && ep.episode != null) {
"${context.getString(R.string.season_short)}${ep.season}:${context.getString(R.string.episode_short)}${ep.episode}" + rowTwoExtra
} else if (ep.episode != null) {
"${context.getString(R.string.episode)} ${ep.episode}" + rowTwoExtra
} else {
(ep.name ?: "") + ""
}
val downloadFormat = context.getString(R.string.download_format)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (ep.poster != null) {
val poster = withContext(Dispatchers.IO) {
context.getImageBitmapFromUrl(ep.poster)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (ep.poster != null) {
val poster = withContext(Dispatchers.IO) {
context.getImageBitmapFromUrl(ep.poster)
}
if (poster != null)
builder.setLargeIcon(poster)
}
if (poster != null)
builder.setLargeIcon(poster)
}
val progressPercentage = progress * 100 / total
val progressMbString = "%.1f".format(progress / 1000000f)
val totalMbString = "%.1f".format(total / 1000000f)
val bigText =
if (state == DownloadType.IsDownloading || state == DownloadType.IsPaused) {
(if (linkName == null) "" else "$linkName\n") + "$rowTwo\n$progressPercentage % ($progressMbString MB/$totalMbString MB)"
val progressPercentage = progress * 100 / total
val progressMbString = "%.1f".format(progress / 1000000f)
val totalMbString = "%.1f".format(total / 1000000f)
val bigText =
if (state == DownloadType.IsDownloading || state == DownloadType.IsPaused) {
(if (linkName == null) "" else "$linkName\n") + "$rowTwo\n$progressPercentage % ($progressMbString MB/$totalMbString MB)"
} else if (state == DownloadType.IsFailed) {
downloadFormat.format(context.getString(R.string.download_failed), rowTwo)
} else if (state == DownloadType.IsDone) {
downloadFormat.format(context.getString(R.string.download_done), rowTwo)
} else {
downloadFormat.format(context.getString(R.string.download_canceled), rowTwo)
}
val bodyStyle = NotificationCompat.BigTextStyle()
bodyStyle.bigText(bigText)
builder.setStyle(bodyStyle)
} else {
val txt = if (state == DownloadType.IsDownloading || state == DownloadType.IsPaused) {
rowTwo
} else if (state == DownloadType.IsFailed) {
downloadFormat.format(context.getString(R.string.download_failed), rowTwo)
} else if (state == DownloadType.IsDone) {
@ -310,86 +329,74 @@ object VideoDownloadManager {
downloadFormat.format(context.getString(R.string.download_canceled), rowTwo)
}
val bodyStyle = NotificationCompat.BigTextStyle()
bodyStyle.bigText(bigText)
builder.setStyle(bodyStyle)
} else {
val txt = if (state == DownloadType.IsDownloading || state == DownloadType.IsPaused) {
rowTwo
} else if (state == DownloadType.IsFailed) {
downloadFormat.format(context.getString(R.string.download_failed), rowTwo)
} else if (state == DownloadType.IsDone) {
downloadFormat.format(context.getString(R.string.download_done), rowTwo)
} else {
downloadFormat.format(context.getString(R.string.download_canceled), rowTwo)
builder.setContentText(txt)
}
builder.setContentText(txt)
}
if ((state == DownloadType.IsDownloading || state == DownloadType.IsPaused) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val actionTypes: MutableList<DownloadActionType> = ArrayList()
// INIT
if (state == DownloadType.IsDownloading) {
actionTypes.add(DownloadActionType.Pause)
actionTypes.add(DownloadActionType.Stop)
}
if ((state == DownloadType.IsDownloading || state == DownloadType.IsPaused) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val actionTypes: MutableList<DownloadActionType> = ArrayList()
// INIT
if (state == DownloadType.IsDownloading) {
actionTypes.add(DownloadActionType.Pause)
actionTypes.add(DownloadActionType.Stop)
}
if (state == DownloadType.IsPaused) {
actionTypes.add(DownloadActionType.Resume)
actionTypes.add(DownloadActionType.Stop)
}
if (state == DownloadType.IsPaused) {
actionTypes.add(DownloadActionType.Resume)
actionTypes.add(DownloadActionType.Stop)
}
// ADD ACTIONS
for ((index, i) in actionTypes.withIndex()) {
val actionResultIntent = Intent(context, VideoDownloadService::class.java)
// ADD ACTIONS
for ((index, i) in actionTypes.withIndex()) {
val actionResultIntent = Intent(context, VideoDownloadService::class.java)
actionResultIntent.putExtra(
"type", when (i) {
DownloadActionType.Resume -> "resume"
DownloadActionType.Pause -> "pause"
DownloadActionType.Stop -> "stop"
}
)
actionResultIntent.putExtra("id", ep.id)
val pending: PendingIntent = PendingIntent.getService(
// BECAUSE episodes lying near will have the same id +1, index will give the same requested as the previous episode, *100000 fixes this
context, (4337 + index * 1000000 + ep.id),
actionResultIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
builder.addAction(
NotificationCompat.Action(
when (i) {
DownloadActionType.Resume -> pressToResumeIcon
DownloadActionType.Pause -> pressToPauseIcon
DownloadActionType.Stop -> pressToStopIcon
}, when (i) {
DownloadActionType.Resume -> context.getString(R.string.resume)
DownloadActionType.Pause -> context.getString(R.string.pause)
DownloadActionType.Stop -> context.getString(R.string.cancel)
}, pending
actionResultIntent.putExtra(
"type", when (i) {
DownloadActionType.Resume -> "resume"
DownloadActionType.Pause -> "pause"
DownloadActionType.Stop -> "stop"
}
)
)
actionResultIntent.putExtra("id", ep.id)
val pending: PendingIntent = PendingIntent.getService(
// BECAUSE episodes lying near will have the same id +1, index will give the same requested as the previous episode, *100000 fixes this
context, (4337 + index * 1000000 + ep.id),
actionResultIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
builder.addAction(
NotificationCompat.Action(
when (i) {
DownloadActionType.Resume -> pressToResumeIcon
DownloadActionType.Pause -> pressToPauseIcon
DownloadActionType.Stop -> pressToStopIcon
}, when (i) {
DownloadActionType.Resume -> context.getString(R.string.resume)
DownloadActionType.Pause -> context.getString(R.string.pause)
DownloadActionType.Stop -> context.getString(R.string.cancel)
}, pending
)
)
}
}
}
if (!hasCreatedNotChanel) {
context.createNotificationChannel()
}
if (!hasCreatedNotChanel) {
context.createNotificationChannel()
}
val notification = builder.build()
notificationCallback(ep.id, notification)
with(NotificationManagerCompat.from(context)) {
// notificationId is a unique int for each notification that you must define
notify(ep.id, notification)
val notification = builder.build()
notificationCallback(ep.id, notification)
with(NotificationManagerCompat.from(context)) {
// notificationId is a unique int for each notification that you must define
notify(ep.id, notification)
}
return notification
} catch (e: Exception) {
logError(e)
return null
}
return notification
// }
}
private const val reservedChars = "|\\?*<\":>+[]/\'"