mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Merge branch 'recloudstream:master' into master
This commit is contained in:
commit
b321dfa072
13 changed files with 220 additions and 76 deletions
|
@ -166,6 +166,8 @@ object CommonActivity {
|
||||||
"Light" -> R.style.LightMode
|
"Light" -> R.style.LightMode
|
||||||
"Amoled" -> R.style.AmoledMode
|
"Amoled" -> R.style.AmoledMode
|
||||||
"AmoledLight" -> R.style.AmoledModeLight
|
"AmoledLight" -> R.style.AmoledModeLight
|
||||||
|
"Monet" -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
|
||||||
|
R.style.MonetMode else R.style.AppTheme
|
||||||
else -> R.style.AppTheme
|
else -> R.style.AppTheme
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,6 +188,10 @@ object CommonActivity {
|
||||||
"Banana" -> R.style.OverlayPrimaryColorBanana
|
"Banana" -> R.style.OverlayPrimaryColorBanana
|
||||||
"Party" -> R.style.OverlayPrimaryColorParty
|
"Party" -> R.style.OverlayPrimaryColorParty
|
||||||
"Pink" -> R.style.OverlayPrimaryColorPink
|
"Pink" -> R.style.OverlayPrimaryColorPink
|
||||||
|
"Monet" -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
|
||||||
|
R.style.OverlayPrimaryColorMonet else R.style.OverlayPrimaryColorNormal
|
||||||
|
"Monet2" -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
|
||||||
|
R.style.OverlayPrimaryColorMonetTwo else R.style.OverlayPrimaryColorNormal
|
||||||
else -> R.style.OverlayPrimaryColorNormal
|
else -> R.style.OverlayPrimaryColorNormal
|
||||||
}
|
}
|
||||||
act.theme.applyStyle(currentTheme, true)
|
act.theme.applyStyle(currentTheme, true)
|
||||||
|
|
|
@ -3,10 +3,9 @@ package com.lagradost.cloudstream3.extractors
|
||||||
import com.lagradost.cloudstream3.SubtitleFile
|
import com.lagradost.cloudstream3.SubtitleFile
|
||||||
import com.lagradost.cloudstream3.apmap
|
import com.lagradost.cloudstream3.apmap
|
||||||
import com.lagradost.cloudstream3.app
|
import com.lagradost.cloudstream3.app
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorApi
|
import com.lagradost.cloudstream3.utils.*
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import kotlinx.coroutines.delay
|
||||||
import com.lagradost.cloudstream3.utils.M3u8Helper
|
import java.net.URI
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
|
||||||
|
|
||||||
class VidSrcExtractor2 : VidSrcExtractor() {
|
class VidSrcExtractor2 : VidSrcExtractor() {
|
||||||
override val mainUrl = "https://vidsrc.me/embed"
|
override val mainUrl = "https://vidsrc.me/embed"
|
||||||
|
@ -27,6 +26,25 @@ open class VidSrcExtractor : ExtractorApi() {
|
||||||
override val mainUrl = "$absoluteUrl/embed"
|
override val mainUrl = "$absoluteUrl/embed"
|
||||||
override val requiresReferer = false
|
override val requiresReferer = false
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/** Infinite function to validate the vidSrc pass */
|
||||||
|
suspend fun validatePass(url: String) {
|
||||||
|
val uri = URI(url)
|
||||||
|
val host = uri.host
|
||||||
|
|
||||||
|
// Basically turn https://tm3p.vidsrc.stream/ -> https://vidsrc.stream/
|
||||||
|
val referer = host.split(".").let {
|
||||||
|
val size = it.size
|
||||||
|
"https://" + it.subList(maxOf(0, size - 2), size).joinToString(".") + "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
app.get(url, referer = referer)
|
||||||
|
delay(60_000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun getUrl(
|
override suspend fun getUrl(
|
||||||
url: String,
|
url: String,
|
||||||
referer: String?,
|
referer: String?,
|
||||||
|
@ -40,7 +58,10 @@ open class VidSrcExtractor : ExtractorApi() {
|
||||||
val datahash = it.attr("data-hash")
|
val datahash = it.attr("data-hash")
|
||||||
if (datahash.isNotBlank()) {
|
if (datahash.isNotBlank()) {
|
||||||
val links = try {
|
val links = try {
|
||||||
app.get("$absoluteUrl/src/$datahash", referer = "https://source.vidsrc.me/").url
|
app.get(
|
||||||
|
"$absoluteUrl/src/$datahash",
|
||||||
|
referer = "https://source.vidsrc.me/"
|
||||||
|
).url
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
""
|
""
|
||||||
}
|
}
|
||||||
|
@ -54,11 +75,28 @@ open class VidSrcExtractor : ExtractorApi() {
|
||||||
val srcresponse = app.get(server, referer = absoluteUrl).text
|
val srcresponse = app.get(server, referer = absoluteUrl).text
|
||||||
val m3u8Regex = Regex("((https:|http:)//.*\\.m3u8)")
|
val m3u8Regex = Regex("((https:|http:)//.*\\.m3u8)")
|
||||||
val srcm3u8 = m3u8Regex.find(srcresponse)?.value ?: return@apmap
|
val srcm3u8 = m3u8Regex.find(srcresponse)?.value ?: return@apmap
|
||||||
M3u8Helper.generateM3u8(
|
val passRegex = Regex("""['"](.*set_pass[^"']*)""")
|
||||||
name,
|
val pass = passRegex.find(srcresponse)?.groupValues?.get(1)?.replace(
|
||||||
|
Regex("""^//"""), "https://"
|
||||||
|
)
|
||||||
|
|
||||||
|
callback.invoke(
|
||||||
|
ExtractorLink(
|
||||||
|
this.name,
|
||||||
|
this.name,
|
||||||
srcm3u8,
|
srcm3u8,
|
||||||
absoluteUrl
|
this.mainUrl,
|
||||||
).forEach(callback)
|
Qualities.Unknown.value,
|
||||||
|
extractorData = pass,
|
||||||
|
isM3u8 = true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// M3u8Helper.generateM3u8(
|
||||||
|
// name,
|
||||||
|
// srcm3u8,
|
||||||
|
// absoluteUrl
|
||||||
|
// ).forEach(callback)
|
||||||
} else {
|
} else {
|
||||||
loadExtractor(linkfixed, url, subtitleCallback, callback)
|
loadExtractor(linkfixed, url, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import kotlin.coroutines.CoroutineContext
|
||||||
import kotlin.coroutines.EmptyCoroutineContext
|
import kotlin.coroutines.EmptyCoroutineContext
|
||||||
|
|
||||||
const val DEBUG_EXCEPTION = "THIS IS A DEBUG EXCEPTION!"
|
const val DEBUG_EXCEPTION = "THIS IS A DEBUG EXCEPTION!"
|
||||||
|
const val DEBUG_PRINT = "DEBUG PRINT"
|
||||||
|
|
||||||
class DebugException(message: String) : Exception("$DEBUG_EXCEPTION\n$message")
|
class DebugException(message: String) : Exception("$DEBUG_EXCEPTION\n$message")
|
||||||
|
|
||||||
|
@ -24,6 +25,12 @@ inline fun debugException(message: () -> String) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun debugPrint(tag: String = DEBUG_PRINT, message: () -> String) {
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Log.d(tag, message.invoke())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline fun debugWarning(message: () -> String) {
|
inline fun debugWarning(message: () -> String) {
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
logError(DebugException(message.invoke()))
|
logError(DebugException(message.invoke()))
|
||||||
|
|
|
@ -8,12 +8,10 @@ import android.content.res.Resources
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.core.net.toUri
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
||||||
|
@ -28,6 +26,7 @@ import com.lagradost.cloudstream3.ui.settings.extensions.RepositoryData
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager.sanitizeFilename
|
import com.lagradost.cloudstream3.utils.VideoDownloadManager.sanitizeFilename
|
||||||
import com.lagradost.cloudstream3.APIHolder.removePluginMapping
|
import com.lagradost.cloudstream3.APIHolder.removePluginMapping
|
||||||
import com.lagradost.cloudstream3.MainActivity.Companion.afterPluginsLoadedEvent
|
import com.lagradost.cloudstream3.MainActivity.Companion.afterPluginsLoadedEvent
|
||||||
|
import com.lagradost.cloudstream3.mvvm.debugPrint
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIES
|
import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIES
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||||
|
@ -37,7 +36,6 @@ import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute
|
||||||
import com.lagradost.cloudstream3.utils.extractorApis
|
import com.lagradost.cloudstream3.utils.extractorApis
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import org.acra.log.debug
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -223,13 +221,14 @@ object PluginManager {
|
||||||
|
|
||||||
// Iterates over all offline plugins, compares to remote repo and returns the plugins which are outdated
|
// Iterates over all offline plugins, compares to remote repo and returns the plugins which are outdated
|
||||||
val outdatedPlugins = getPluginsOnline().map { savedData ->
|
val outdatedPlugins = getPluginsOnline().map { savedData ->
|
||||||
onlinePlugins.filter { onlineData -> savedData.internalName == onlineData.second.internalName }
|
onlinePlugins
|
||||||
|
.filter { onlineData -> savedData.internalName == onlineData.second.internalName }
|
||||||
.map { onlineData ->
|
.map { onlineData ->
|
||||||
OnlinePluginData(savedData, onlineData)
|
OnlinePluginData(savedData, onlineData)
|
||||||
}
|
}
|
||||||
}.flatten().distinctBy { it.onlineData.second.url }
|
}.flatten().distinctBy { it.onlineData.second.url }
|
||||||
|
|
||||||
debug {
|
debugPrint {
|
||||||
"Outdated plugins: ${outdatedPlugins.filter { it.isOutdated }}"
|
"Outdated plugins: ${outdatedPlugins.filter { it.isOutdated }}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +243,7 @@ object PluginManager {
|
||||||
activity,
|
activity,
|
||||||
pluginData.onlineData.second.url,
|
pluginData.onlineData.second.url,
|
||||||
pluginData.savedData.internalName,
|
pluginData.savedData.internalName,
|
||||||
pluginData.onlineData.first
|
File(pluginData.savedData.filePath)
|
||||||
).let { success ->
|
).let { success ->
|
||||||
if (success)
|
if (success)
|
||||||
updatedPlugins.add(pluginData.onlineData.second.name)
|
updatedPlugins.add(pluginData.onlineData.second.name)
|
||||||
|
@ -417,24 +416,45 @@ object PluginManager {
|
||||||
) + "." + name.hashCode()
|
) + "." + name.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for fresh installs
|
||||||
|
* */
|
||||||
suspend fun downloadAndLoadPlugin(
|
suspend fun downloadAndLoadPlugin(
|
||||||
activity: Activity,
|
activity: Activity,
|
||||||
pluginUrl: String,
|
pluginUrl: String,
|
||||||
internalName: String,
|
internalName: String,
|
||||||
repositoryUrl: String
|
repositoryUrl: String
|
||||||
): Boolean {
|
): Boolean {
|
||||||
try {
|
|
||||||
val folderName = getPluginSanitizedFileName(repositoryUrl) // Guaranteed unique
|
val folderName = getPluginSanitizedFileName(repositoryUrl) // Guaranteed unique
|
||||||
val fileName = getPluginSanitizedFileName(internalName)
|
val fileName = getPluginSanitizedFileName(internalName)
|
||||||
unloadPlugin("${activity.filesDir}/${ONLINE_PLUGINS_FOLDER}/${folderName}/$fileName.cs3")
|
val file = File("${activity.filesDir}/${ONLINE_PLUGINS_FOLDER}/${folderName}/$fileName.cs3")
|
||||||
|
downloadAndLoadPlugin(activity, pluginUrl, internalName, file)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
Log.d(TAG, "Downloading plugin: $pluginUrl to $folderName/$fileName")
|
/**
|
||||||
|
* Used for updates.
|
||||||
|
*
|
||||||
|
* Uses a file instead of repository url, as extensions can get moved it is better to directly
|
||||||
|
* update the files instead of getting the filepath from repo url.
|
||||||
|
* */
|
||||||
|
private suspend fun downloadAndLoadPlugin(
|
||||||
|
activity: Activity,
|
||||||
|
pluginUrl: String,
|
||||||
|
internalName: String,
|
||||||
|
file: File,
|
||||||
|
): Boolean {
|
||||||
|
try {
|
||||||
|
unloadPlugin(file.absolutePath)
|
||||||
|
|
||||||
|
Log.d(TAG, "Downloading plugin: $pluginUrl to ${file.absolutePath}")
|
||||||
// The plugin file needs to be salted with the repository url hash as to allow multiple repositories with the same internal plugin names
|
// The plugin file needs to be salted with the repository url hash as to allow multiple repositories with the same internal plugin names
|
||||||
val file = downloadPluginToFile(activity, pluginUrl, fileName, folderName)
|
val newFile = downloadPluginToFile(pluginUrl, file)
|
||||||
return loadPlugin(
|
return loadPlugin(
|
||||||
activity,
|
activity,
|
||||||
file ?: return false,
|
newFile ?: return false,
|
||||||
PluginData(internalName, pluginUrl, true, file.absolutePath, PLUGIN_VERSION_NOT_SET)
|
PluginData(internalName, pluginUrl, true, newFile.absolutePath, PLUGIN_VERSION_NOT_SET)
|
||||||
)
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logError(e)
|
logError(e)
|
||||||
|
@ -468,7 +488,8 @@ object PluginManager {
|
||||||
// the NotificationChannel class is new and not in the support library
|
// the NotificationChannel class is new and not in the support library
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
val name = EXTENSIONS_CHANNEL_NAME //getString(R.string.channel_name)
|
val name = EXTENSIONS_CHANNEL_NAME //getString(R.string.channel_name)
|
||||||
val descriptionText = EXTENSIONS_CHANNEL_DESCRIPT//getString(R.string.channel_description)
|
val descriptionText =
|
||||||
|
EXTENSIONS_CHANNEL_DESCRIPT//getString(R.string.channel_description)
|
||||||
val importance = NotificationManager.IMPORTANCE_LOW
|
val importance = NotificationManager.IMPORTANCE_LOW
|
||||||
val channel = NotificationChannel(EXTENSIONS_CHANNEL_ID, name, importance).apply {
|
val channel = NotificationChannel(EXTENSIONS_CHANNEL_ID, name, importance).apply {
|
||||||
description = descriptionText
|
description = descriptionText
|
||||||
|
@ -479,6 +500,7 @@ object PluginManager {
|
||||||
notificationManager.createNotificationChannel(channel)
|
notificationManager.createNotificationChannel(channel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createNotification(
|
private fun createNotification(
|
||||||
context: Context,
|
context: Context,
|
||||||
extensionNames: List<String>
|
extensionNames: List<String>
|
||||||
|
@ -497,8 +519,10 @@ object PluginManager {
|
||||||
.setColor(context.colorFromAttribute(R.attr.colorPrimary))
|
.setColor(context.colorFromAttribute(R.attr.colorPrimary))
|
||||||
.setContentTitle(context.getString(R.string.plugins_updated, extensionNames.size))
|
.setContentTitle(context.getString(R.string.plugins_updated, extensionNames.size))
|
||||||
.setSmallIcon(R.drawable.ic_baseline_extension_24)
|
.setSmallIcon(R.drawable.ic_baseline_extension_24)
|
||||||
.setStyle(NotificationCompat.BigTextStyle()
|
.setStyle(
|
||||||
.bigText(content))
|
NotificationCompat.BigTextStyle()
|
||||||
|
.bigText(content)
|
||||||
|
)
|
||||||
.setContentText(content)
|
.setContentText(content)
|
||||||
|
|
||||||
if (!hasCreatedNotChanel) {
|
if (!hasCreatedNotChanel) {
|
||||||
|
@ -508,7 +532,7 @@ object PluginManager {
|
||||||
val notification = builder.build()
|
val notification = builder.build()
|
||||||
with(NotificationManagerCompat.from(context)) {
|
with(NotificationManagerCompat.from(context)) {
|
||||||
// notificationId is a unique int for each notification that you must define
|
// notificationId is a unique int for each notification that you must define
|
||||||
notify((System.currentTimeMillis()/1000).toInt(), notification)
|
notify((System.currentTimeMillis() / 1000).toInt(), notification)
|
||||||
}
|
}
|
||||||
return notification
|
return notification
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|
|
@ -84,7 +84,7 @@ object RepositoryManager {
|
||||||
// Normal parsed function not working?
|
// Normal parsed function not working?
|
||||||
// return response.parsedSafe()
|
// return response.parsedSafe()
|
||||||
tryParseJson<Array<SitePlugin>>(response.text)?.toList() ?: emptyList()
|
tryParseJson<Array<SitePlugin>>(response.text)?.toList() ?: emptyList()
|
||||||
} catch (t : Throwable) {
|
} catch (t: Throwable) {
|
||||||
logError(t)
|
logError(t)
|
||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
|
@ -102,9 +102,27 @@ object RepositoryManager {
|
||||||
}.flatten()
|
}.flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun downloadPluginToFile(
|
||||||
|
pluginUrl: String,
|
||||||
|
file: File
|
||||||
|
): File? {
|
||||||
|
return suspendSafeApiCall {
|
||||||
|
file.mkdirs()
|
||||||
|
|
||||||
|
// Overwrite if exists
|
||||||
|
if (file.exists()) { file.delete() }
|
||||||
|
file.createNewFile()
|
||||||
|
|
||||||
|
val body = app.get(pluginUrl).okhttpResponse.body
|
||||||
|
write(body.byteStream(), file.outputStream())
|
||||||
|
file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun downloadPluginToFile(
|
suspend fun downloadPluginToFile(
|
||||||
context: Context,
|
context: Context,
|
||||||
pluginUrl: String,
|
pluginUrl: String,
|
||||||
|
/** Filename without .cs3 */
|
||||||
fileName: String,
|
fileName: String,
|
||||||
folder: String
|
folder: String
|
||||||
): File? {
|
): File? {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.lagradost.cloudstream3.ui.settings
|
package com.lagradost.cloudstream3.ui.settings
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
|
@ -83,8 +84,20 @@ class SettingsUI : PreferenceFragmentCompat() {
|
||||||
}
|
}
|
||||||
|
|
||||||
getPref(R.string.app_theme_key)?.setOnPreferenceClickListener {
|
getPref(R.string.app_theme_key)?.setOnPreferenceClickListener {
|
||||||
val prefNames = resources.getStringArray(R.array.themes_names)
|
val prefNames = resources.getStringArray(R.array.themes_names).toMutableList()
|
||||||
val prefValues = resources.getStringArray(R.array.themes_names_values)
|
val prefValues = resources.getStringArray(R.array.themes_names_values).toMutableList()
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { // remove monet on android 11 and less
|
||||||
|
val toRemove = prefValues
|
||||||
|
.mapIndexed { idx, s -> if (s.startsWith("Monet")) idx else null }
|
||||||
|
.filterNotNull()
|
||||||
|
var offset = 0
|
||||||
|
toRemove.forEach { idx ->
|
||||||
|
prefNames.removeAt(idx - offset)
|
||||||
|
prefValues.removeAt(idx - offset)
|
||||||
|
offset += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val currentLayout =
|
val currentLayout =
|
||||||
settingsManager.getString(getString(R.string.app_theme_key), prefValues.first())
|
settingsManager.getString(getString(R.string.app_theme_key), prefValues.first())
|
||||||
|
@ -107,8 +120,20 @@ class SettingsUI : PreferenceFragmentCompat() {
|
||||||
return@setOnPreferenceClickListener true
|
return@setOnPreferenceClickListener true
|
||||||
}
|
}
|
||||||
getPref(R.string.primary_color_key)?.setOnPreferenceClickListener {
|
getPref(R.string.primary_color_key)?.setOnPreferenceClickListener {
|
||||||
val prefNames = resources.getStringArray(R.array.themes_overlay_names)
|
val prefNames = resources.getStringArray(R.array.themes_overlay_names).toMutableList()
|
||||||
val prefValues = resources.getStringArray(R.array.themes_overlay_names_values)
|
val prefValues = resources.getStringArray(R.array.themes_overlay_names_values).toMutableList()
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { // remove monet on android 11 and less
|
||||||
|
val toRemove = prefValues
|
||||||
|
.mapIndexed { idx, s -> if (s.startsWith("Monet")) idx else null }
|
||||||
|
.filterNotNull()
|
||||||
|
var offset = 0
|
||||||
|
toRemove.forEach { idx ->
|
||||||
|
prefNames.removeAt(idx - offset)
|
||||||
|
prefValues.removeAt(idx - offset)
|
||||||
|
offset += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val currentLayout =
|
val currentLayout =
|
||||||
settingsManager.getString(getString(R.string.primary_color_key), prefValues.first())
|
settingsManager.getString(getString(R.string.primary_color_key), prefValues.first())
|
||||||
|
|
|
@ -3,21 +3,19 @@ package com.lagradost.cloudstream3.ui.settings.extensions
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.apmap
|
import com.lagradost.cloudstream3.apmap
|
||||||
import com.lagradost.cloudstream3.mvvm.Some
|
import com.lagradost.cloudstream3.mvvm.Some
|
||||||
import com.lagradost.cloudstream3.mvvm.debugAssert
|
import com.lagradost.cloudstream3.mvvm.debugAssert
|
||||||
import com.lagradost.cloudstream3.mvvm.launchSafe
|
|
||||||
import com.lagradost.cloudstream3.plugins.PluginManager
|
import com.lagradost.cloudstream3.plugins.PluginManager
|
||||||
import com.lagradost.cloudstream3.plugins.PluginManager.getPluginsOnline
|
import com.lagradost.cloudstream3.plugins.PluginManager.getPluginsOnline
|
||||||
import com.lagradost.cloudstream3.plugins.RepositoryManager
|
import com.lagradost.cloudstream3.plugins.RepositoryManager
|
||||||
import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIES
|
import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIES
|
||||||
import com.lagradost.cloudstream3.ui.result.UiText
|
import com.lagradost.cloudstream3.ui.result.UiText
|
||||||
import com.lagradost.cloudstream3.ui.result.txt
|
import com.lagradost.cloudstream3.ui.result.txt
|
||||||
import kotlinx.coroutines.launch
|
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||||
|
|
||||||
data class RepositoryData(
|
data class RepositoryData(
|
||||||
@JsonProperty("name") val name: String,
|
@JsonProperty("name") val name: String,
|
||||||
|
@ -46,7 +44,8 @@ class ExtensionsViewModel : ViewModel() {
|
||||||
val pluginStats: LiveData<Some<PluginStats>> = _pluginStats
|
val pluginStats: LiveData<Some<PluginStats>> = _pluginStats
|
||||||
|
|
||||||
//TODO CACHE GET REQUESTS
|
//TODO CACHE GET REQUESTS
|
||||||
fun loadStats() = viewModelScope.launchSafe {
|
// DO not use viewModelScope.launchSafe, it will ANR on slow internet
|
||||||
|
fun loadStats() = ioSafe {
|
||||||
val urls = (getKey<Array<RepositoryData>>(REPOSITORIES_KEY)
|
val urls = (getKey<Array<RepositoryData>>(REPOSITORIES_KEY)
|
||||||
?: emptyArray()) + PREBUILT_REPOSITORIES
|
?: emptyArray()) + PREBUILT_REPOSITORIES
|
||||||
|
|
||||||
|
@ -61,6 +60,7 @@ class ExtensionsViewModel : ViewModel() {
|
||||||
PluginManager.OnlinePluginData(savedData, onlineData)
|
PluginManager.OnlinePluginData(savedData, onlineData)
|
||||||
}
|
}
|
||||||
}.flatten().distinctBy { it.onlineData.second.url }
|
}.flatten().distinctBy { it.onlineData.second.url }
|
||||||
|
|
||||||
val total = onlinePlugins.count()
|
val total = onlinePlugins.count()
|
||||||
val disabled = outdatedPlugins.count { it.isDisabled }
|
val disabled = outdatedPlugins.count { it.isDisabled }
|
||||||
val downloadedTotal = outdatedPlugins.count()
|
val downloadedTotal = outdatedPlugins.count()
|
||||||
|
|
|
@ -14,19 +14,6 @@
|
||||||
<item>@id/cast_button_type_forward_30_seconds</item>
|
<item>@id/cast_button_type_forward_30_seconds</item>
|
||||||
</array>
|
</array>
|
||||||
|
|
||||||
<array name="media_type_pref">
|
|
||||||
<item>Todos</item>
|
|
||||||
<item>Películas y TV</item>
|
|
||||||
<item>Anime</item>
|
|
||||||
<item>Documental</item>
|
|
||||||
</array>
|
|
||||||
<array name="media_type_pref_values">
|
|
||||||
<item>0</item>
|
|
||||||
<item>1</item>
|
|
||||||
<item>2</item>
|
|
||||||
<item>3</item>
|
|
||||||
</array>
|
|
||||||
|
|
||||||
<array name="limit_title_rez_pref_names">
|
<array name="limit_title_rez_pref_names">
|
||||||
<item>@string/resolution_and_title</item>
|
<item>@string/resolution_and_title</item>
|
||||||
<item>@string/title</item>
|
<item>@string/title</item>
|
||||||
|
@ -222,6 +209,8 @@
|
||||||
<item>Banana</item>
|
<item>Banana</item>
|
||||||
<item>Fiesta</item>
|
<item>Fiesta</item>
|
||||||
<item>Dolor rosa</item>
|
<item>Dolor rosa</item>
|
||||||
|
<item>Material You</item>
|
||||||
|
<item>Material You (Secondary)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="themes_overlay_names_values">
|
<string-array name="themes_overlay_names_values">
|
||||||
<item>Normal</item>
|
<item>Normal</item>
|
||||||
|
@ -240,19 +229,24 @@
|
||||||
<item>Banana</item>
|
<item>Banana</item>
|
||||||
<item>Party</item>
|
<item>Party</item>
|
||||||
<item>Pink</item>
|
<item>Pink</item>
|
||||||
|
<item>Monet</item>
|
||||||
|
<item>Monet2</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
|
||||||
<string-array name="themes_names">
|
<string-array name="themes_names">
|
||||||
<item>Oscuro</item>
|
<item>Oscuro</item>
|
||||||
<item>Gris</item>
|
<item>Gris</item>
|
||||||
<item>Amoled</item>
|
<item>Amoled</item>
|
||||||
<item>Destello</item>
|
<item>Destello</item>
|
||||||
|
<item>Material You</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="themes_names_values">
|
<string-array name="themes_names_values">
|
||||||
<item>AmoledLight</item>
|
<item>AmoledLight</item>
|
||||||
<item>Black</item>
|
<item>Black</item>
|
||||||
<item>Amoled</item>
|
<item>Amoled</item>
|
||||||
<item>Light</item>
|
<item>Light</item>
|
||||||
|
<item>Monet</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!--https://github.com/videolan/vlc-android/blob/72ccfb93db027b49855760001d1a930fa657c5a8/application/resources/src/main/res/values/arrays.xml#L266-->
|
<!--https://github.com/videolan/vlc-android/blob/72ccfb93db027b49855760001d1a930fa657c5a8/application/resources/src/main/res/values/arrays.xml#L266-->
|
||||||
|
|
|
@ -218,6 +218,8 @@
|
||||||
<item>Bananowy</item>
|
<item>Bananowy</item>
|
||||||
<item>Łososiowy</item>
|
<item>Łososiowy</item>
|
||||||
<item>Świnko peppowy</item>
|
<item>Świnko peppowy</item>
|
||||||
|
<item>Material You</item>
|
||||||
|
<item>Material You (drugorzędny)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="themes_overlay_names_values">
|
<string-array name="themes_overlay_names_values">
|
||||||
<item>Normal</item>
|
<item>Normal</item>
|
||||||
|
@ -236,19 +238,24 @@
|
||||||
<item>Banana</item>
|
<item>Banana</item>
|
||||||
<item>Party</item>
|
<item>Party</item>
|
||||||
<item>Pink</item>
|
<item>Pink</item>
|
||||||
|
<item>Monet</item>
|
||||||
|
<item>Monet2</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
|
||||||
<string-array name="themes_names">
|
<string-array name="themes_names">
|
||||||
<item>Ciemny</item>
|
<item>Ciemny</item>
|
||||||
<item>Szary</item>
|
<item>Szary</item>
|
||||||
<item>Amoled</item>
|
<item>Amoled</item>
|
||||||
<item>Flashbang</item>
|
<item>Flashbang</item>
|
||||||
|
<item>Material You</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="themes_names_values">
|
<string-array name="themes_names_values">
|
||||||
<item>AmoledLight</item>
|
<item>AmoledLight</item>
|
||||||
<item>Black</item>
|
<item>Black</item>
|
||||||
<item>Amoled</item>
|
<item>Amoled</item>
|
||||||
<item>Light</item>
|
<item>Light</item>
|
||||||
|
<item>Monet</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!--https://github.com/videolan/vlc-android/blob/72ccfb93db027b49855760001d1a930fa657c5a8/application/resources/src/main/res/values/arrays.xml#L266-->
|
<!--https://github.com/videolan/vlc-android/blob/72ccfb93db027b49855760001d1a930fa657c5a8/application/resources/src/main/res/values/arrays.xml#L266-->
|
||||||
|
|
|
@ -14,19 +14,6 @@
|
||||||
<item>@id/cast_button_type_forward_30_seconds</item>
|
<item>@id/cast_button_type_forward_30_seconds</item>
|
||||||
</array>
|
</array>
|
||||||
|
|
||||||
<array name="media_type_pref">
|
|
||||||
<item>Hepsi</item>
|
|
||||||
<item>Film ve Dizi</item>
|
|
||||||
<item>Anime</item>
|
|
||||||
<item>Belgesel</item>
|
|
||||||
</array>
|
|
||||||
<array name="media_type_pref_values">
|
|
||||||
<item>0</item>
|
|
||||||
<item>1</item>
|
|
||||||
<item>2</item>
|
|
||||||
<item>3</item>
|
|
||||||
</array>
|
|
||||||
|
|
||||||
<array name="limit_title_rez_pref_names">
|
<array name="limit_title_rez_pref_names">
|
||||||
<item>@string/resolution_and_title</item>
|
<item>@string/resolution_and_title</item>
|
||||||
<item>@string/title</item>
|
<item>@string/title</item>
|
||||||
|
@ -222,6 +209,8 @@
|
||||||
<item>Muz</item>
|
<item>Muz</item>
|
||||||
<item>Parti</item>
|
<item>Parti</item>
|
||||||
<item>Pembe</item>
|
<item>Pembe</item>
|
||||||
|
<item>Material You</item>
|
||||||
|
<item>Material You (Secondary)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="themes_overlay_names_values">
|
<string-array name="themes_overlay_names_values">
|
||||||
<item>Normal</item>
|
<item>Normal</item>
|
||||||
|
@ -240,19 +229,24 @@
|
||||||
<item>Banana</item>
|
<item>Banana</item>
|
||||||
<item>Party</item>
|
<item>Party</item>
|
||||||
<item>Pink</item>
|
<item>Pink</item>
|
||||||
|
<item>Monet</item>
|
||||||
|
<item>Monet2</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
|
||||||
<string-array name="themes_names">
|
<string-array name="themes_names">
|
||||||
<item>Koyu</item>
|
<item>Koyu</item>
|
||||||
<item>Gri</item>
|
<item>Gri</item>
|
||||||
<item>Amoled</item>
|
<item>Amoled</item>
|
||||||
<item>Flaş Bombası</item>
|
<item>Flaş Bombası</item>
|
||||||
|
<item>Material You</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="themes_names_values">
|
<string-array name="themes_names_values">
|
||||||
<item>AmoledLight</item>
|
<item>AmoledLight</item>
|
||||||
<item>Black</item>
|
<item>Black</item>
|
||||||
<item>Amoled</item>
|
<item>Amoled</item>
|
||||||
<item>Light</item>
|
<item>Light</item>
|
||||||
|
<item>Monet</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!--https://github.com/videolan/vlc-android/blob/72ccfb93db027b49855760001d1a930fa657c5a8/application/resources/src/main/res/values/arrays.xml#L266-->
|
<!--https://github.com/videolan/vlc-android/blob/72ccfb93db027b49855760001d1a930fa657c5a8/application/resources/src/main/res/values/arrays.xml#L266-->
|
||||||
|
|
|
@ -14,18 +14,6 @@
|
||||||
<item>@id/cast_button_type_forward_30_seconds</item>
|
<item>@id/cast_button_type_forward_30_seconds</item>
|
||||||
</array>
|
</array>
|
||||||
|
|
||||||
<array name="media_type_pref">
|
|
||||||
<item>Tất cả</item>
|
|
||||||
<item>Phim lẻ và Phim bộ</item>
|
|
||||||
<item>Anime</item>
|
|
||||||
<item>Phim tài liệu</item>
|
|
||||||
</array>
|
|
||||||
<array name="media_type_pref_values">
|
|
||||||
<item>0</item>
|
|
||||||
<item>1</item>
|
|
||||||
<item>2</item>
|
|
||||||
<item>3</item>
|
|
||||||
</array>
|
|
||||||
|
|
||||||
<array name="limit_title_rez_pref_names">
|
<array name="limit_title_rez_pref_names">
|
||||||
<item>@string/resolution_and_title</item>
|
<item>@string/resolution_and_title</item>
|
||||||
|
@ -222,6 +210,8 @@
|
||||||
<item>Vàng</item>
|
<item>Vàng</item>
|
||||||
<item>Hồng</item>
|
<item>Hồng</item>
|
||||||
<item>Hồng đậm</item>
|
<item>Hồng đậm</item>
|
||||||
|
<item>Material You</item>
|
||||||
|
<item>Material You (Secondary)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="themes_overlay_names_values">
|
<string-array name="themes_overlay_names_values">
|
||||||
<item>Normal</item>
|
<item>Normal</item>
|
||||||
|
@ -240,19 +230,24 @@
|
||||||
<item>Banana</item>
|
<item>Banana</item>
|
||||||
<item>Party</item>
|
<item>Party</item>
|
||||||
<item>Pink</item>
|
<item>Pink</item>
|
||||||
|
<item>Monet</item>
|
||||||
|
<item>Monet2</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
|
||||||
<string-array name="themes_names">
|
<string-array name="themes_names">
|
||||||
<item>Tối</item>
|
<item>Tối</item>
|
||||||
<item>Xám</item>
|
<item>Xám</item>
|
||||||
<item>Amoled</item>
|
<item>Amoled</item>
|
||||||
<item>Sáng</item>
|
<item>Sáng</item>
|
||||||
|
<item>Material You</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="themes_names_values">
|
<string-array name="themes_names_values">
|
||||||
<item>AmoledLight</item>
|
<item>AmoledLight</item>
|
||||||
<item>Black</item>
|
<item>Black</item>
|
||||||
<item>Amoled</item>
|
<item>Amoled</item>
|
||||||
<item>Light</item>
|
<item>Light</item>
|
||||||
|
<item>Monet</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!--https://github.com/videolan/vlc-android/blob/72ccfb93db027b49855760001d1a930fa657c5a8/application/resources/src/main/res/values/arrays.xml#L266-->
|
<!--https://github.com/videolan/vlc-android/blob/72ccfb93db027b49855760001d1a930fa657c5a8/application/resources/src/main/res/values/arrays.xml#L266-->
|
||||||
|
|
|
@ -228,6 +228,8 @@
|
||||||
<item>Banana</item>
|
<item>Banana</item>
|
||||||
<item>Party</item>
|
<item>Party</item>
|
||||||
<item>Pink Pain</item>
|
<item>Pink Pain</item>
|
||||||
|
<item>Material You</item>
|
||||||
|
<item>Material You (Secondary)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="themes_overlay_names_values">
|
<string-array name="themes_overlay_names_values">
|
||||||
<item>Normal</item>
|
<item>Normal</item>
|
||||||
|
@ -246,6 +248,8 @@
|
||||||
<item>Banana</item>
|
<item>Banana</item>
|
||||||
<item>Party</item>
|
<item>Party</item>
|
||||||
<item>Pink</item>
|
<item>Pink</item>
|
||||||
|
<item>Monet</item>
|
||||||
|
<item>Monet2</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="themes_names">
|
<string-array name="themes_names">
|
||||||
|
@ -253,12 +257,14 @@
|
||||||
<item>Gray</item>
|
<item>Gray</item>
|
||||||
<item>Amoled</item>
|
<item>Amoled</item>
|
||||||
<item>Flashbang</item>
|
<item>Flashbang</item>
|
||||||
|
<item>Material You</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="themes_names_values">
|
<string-array name="themes_names_values">
|
||||||
<item>AmoledLight</item>
|
<item>AmoledLight</item>
|
||||||
<item>Black</item>
|
<item>Black</item>
|
||||||
<item>Amoled</item>
|
<item>Amoled</item>
|
||||||
<item>Light</item>
|
<item>Light</item>
|
||||||
|
<item>Monet</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="extension_statuses">
|
<string-array name="extension_statuses">
|
||||||
|
|
|
@ -95,6 +95,16 @@
|
||||||
<item name="white">#000</item>
|
<item name="white">#000</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="MonetMode">
|
||||||
|
<item name="primaryGrayBackground">@color/material_dynamic_neutral20</item>
|
||||||
|
<item name="primaryBlackBackground">@color/material_dynamic_neutral10</item>
|
||||||
|
<item name="iconGrayBackground">@color/material_dynamic_neutral20</item>
|
||||||
|
<item name="boxItemBackground">@color/material_dynamic_neutral20</item>
|
||||||
|
<item name="textColor">@color/material_dynamic_neutral90</item>
|
||||||
|
<item name="grayTextColor">@color/material_dynamic_neutral60</item>
|
||||||
|
<item name="white">@color/material_dynamic_neutral90</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="OverlayPrimaryColorNormal">
|
<style name="OverlayPrimaryColorNormal">
|
||||||
<item name="colorPrimary">@color/colorPrimary</item>
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
<item name="android:colorPrimary">@color/colorPrimary</item>
|
<item name="android:colorPrimary">@color/colorPrimary</item>
|
||||||
|
@ -105,6 +115,26 @@
|
||||||
<item name="android:colorAccent">@color/colorAccent</item>
|
<item name="android:colorAccent">@color/colorAccent</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="OverlayPrimaryColorMonet">
|
||||||
|
<item name="colorPrimary">@color/material_dynamic_primary80</item>
|
||||||
|
<item name="android:colorPrimary">@color/material_dynamic_primary80</item>
|
||||||
|
<item name="colorPrimaryDark">@color/material_dynamic_primary30</item>
|
||||||
|
<item name="colorAccent">@color/material_dynamic_primary80</item>
|
||||||
|
<item name="colorOnPrimary">@color/material_dynamic_primary20</item>
|
||||||
|
<!-- Needed for leanback fuckery -->
|
||||||
|
<item name="android:colorAccent">@color/material_dynamic_primary30</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="OverlayPrimaryColorMonetTwo">
|
||||||
|
<item name="colorPrimary">@color/material_dynamic_tertiary80</item>
|
||||||
|
<item name="android:colorPrimary">@color/material_dynamic_tertiary80</item>
|
||||||
|
<item name="colorPrimaryDark">@color/material_dynamic_tertiary30</item>
|
||||||
|
<item name="colorAccent">@color/material_dynamic_tertiary80</item>
|
||||||
|
<item name="colorOnPrimary">@color/material_dynamic_tertiary20</item>
|
||||||
|
<!-- Needed for leanback fuckery -->
|
||||||
|
<item name="android:colorAccent">@color/material_dynamic_tertiary30</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="OverlayPrimaryColorBlue">
|
<style name="OverlayPrimaryColorBlue">
|
||||||
<item name="colorPrimary">@color/colorPrimaryBlue</item>
|
<item name="colorPrimary">@color/colorPrimaryBlue</item>
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryBlue</item>
|
<item name="android:colorPrimary">@color/colorPrimaryBlue</item>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue