diff --git a/app/src/main/java/com/lagradost/cloudstream3/CommonActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/CommonActivity.kt index db700f20..c6d1d53f 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/CommonActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/CommonActivity.kt @@ -166,6 +166,7 @@ object CommonActivity { "Light" -> R.style.LightMode "Amoled" -> R.style.AmoledMode "AmoledLight" -> R.style.AmoledModeLight + "Monet" -> R.style.MonetMode else -> R.style.AppTheme } @@ -188,6 +189,8 @@ object CommonActivity { "Banana" -> R.style.OverlayPrimaryColorBanana "Party" -> R.style.OverlayPrimaryColorParty "Pink" -> R.style.OverlayPrimaryColorPink + "Monet" -> R.style.OverlayPrimaryColorMonet + "Monet2" -> R.style.OverlayPrimaryColorMonetTwo else -> R.style.OverlayPrimaryColorNormal } act.theme.applyStyle(currentTheme, true) diff --git a/app/src/main/java/com/lagradost/cloudstream3/mvvm/ArchComponentExt.kt b/app/src/main/java/com/lagradost/cloudstream3/mvvm/ArchComponentExt.kt index 5c3276fa..e5c03d64 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/mvvm/ArchComponentExt.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/mvvm/ArchComponentExt.kt @@ -15,6 +15,7 @@ import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext const val DEBUG_EXCEPTION = "THIS IS A DEBUG EXCEPTION!" +const val DEBUG_PRINT = "DEBUG PRINT" 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) { if (BuildConfig.DEBUG) { logError(DebugException(message.invoke())) diff --git a/app/src/main/java/com/lagradost/cloudstream3/plugins/PluginManager.kt b/app/src/main/java/com/lagradost/cloudstream3/plugins/PluginManager.kt index c4d1f66f..bf7e694c 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/plugins/PluginManager.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/plugins/PluginManager.kt @@ -8,12 +8,10 @@ import android.content.res.Resources import android.os.Environment import android.widget.Toast import android.content.Context -import android.content.Intent import android.os.Build import android.util.Log import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat -import androidx.core.net.toUri import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* 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.APIHolder.removePluginMapping import com.lagradost.cloudstream3.MainActivity.Companion.afterPluginsLoadedEvent +import com.lagradost.cloudstream3.mvvm.debugPrint import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIES 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 kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock -import org.acra.log.debug import java.io.File import java.io.InputStreamReader 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 val outdatedPlugins = getPluginsOnline().map { savedData -> - onlinePlugins.filter { onlineData -> savedData.internalName == onlineData.second.internalName } + onlinePlugins + .filter { onlineData -> savedData.internalName == onlineData.second.internalName } .map { onlineData -> OnlinePluginData(savedData, onlineData) } }.flatten().distinctBy { it.onlineData.second.url } - debug { + debugPrint { "Outdated plugins: ${outdatedPlugins.filter { it.isOutdated }}" } @@ -244,7 +243,7 @@ object PluginManager { activity, pluginData.onlineData.second.url, pluginData.savedData.internalName, - pluginData.onlineData.first + File(pluginData.savedData.filePath) ).let { success -> if (success) updatedPlugins.add(pluginData.onlineData.second.name) @@ -417,24 +416,45 @@ object PluginManager { ) + "." + name.hashCode() } + + /** + * Used for fresh installs + * */ suspend fun downloadAndLoadPlugin( activity: Activity, pluginUrl: String, internalName: String, repositoryUrl: String ): Boolean { - try { - val folderName = getPluginSanitizedFileName(repositoryUrl) // Guaranteed unique - val fileName = getPluginSanitizedFileName(internalName) - unloadPlugin("${activity.filesDir}/${ONLINE_PLUGINS_FOLDER}/${folderName}/$fileName.cs3") + val folderName = getPluginSanitizedFileName(repositoryUrl) // Guaranteed unique + val fileName = getPluginSanitizedFileName(internalName) + 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 - val file = downloadPluginToFile(activity, pluginUrl, fileName, folderName) + val newFile = downloadPluginToFile(pluginUrl, file) return loadPlugin( activity, - file ?: return false, - PluginData(internalName, pluginUrl, true, file.absolutePath, PLUGIN_VERSION_NOT_SET) + newFile ?: return false, + PluginData(internalName, pluginUrl, true, newFile.absolutePath, PLUGIN_VERSION_NOT_SET) ) } catch (e: Exception) { logError(e) @@ -468,7 +488,8 @@ object PluginManager { // the NotificationChannel class is new and not in the support library if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 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 channel = NotificationChannel(EXTENSIONS_CHANNEL_ID, name, importance).apply { description = descriptionText @@ -479,10 +500,11 @@ object PluginManager { notificationManager.createNotificationChannel(channel) } } + private fun createNotification( context: Context, extensionNames: List - ): Notification? { + ): Notification? { try { if (extensionNames.isEmpty()) return null @@ -497,8 +519,10 @@ object PluginManager { .setColor(context.colorFromAttribute(R.attr.colorPrimary)) .setContentTitle(context.getString(R.string.plugins_updated, extensionNames.size)) .setSmallIcon(R.drawable.ic_baseline_extension_24) - .setStyle(NotificationCompat.BigTextStyle() - .bigText(content)) + .setStyle( + NotificationCompat.BigTextStyle() + .bigText(content) + ) .setContentText(content) if (!hasCreatedNotChanel) { @@ -508,7 +532,7 @@ object PluginManager { val notification = builder.build() with(NotificationManagerCompat.from(context)) { // 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 } catch (e: Exception) { diff --git a/app/src/main/java/com/lagradost/cloudstream3/plugins/RepositoryManager.kt b/app/src/main/java/com/lagradost/cloudstream3/plugins/RepositoryManager.kt index ee0b60b8..e3203787 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/plugins/RepositoryManager.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/plugins/RepositoryManager.kt @@ -84,7 +84,7 @@ object RepositoryManager { // Normal parsed function not working? // return response.parsedSafe() tryParseJson>(response.text)?.toList() ?: emptyList() - } catch (t : Throwable) { + } catch (t: Throwable) { logError(t) emptyList() } @@ -102,9 +102,27 @@ object RepositoryManager { }.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( context: Context, pluginUrl: String, + /** Filename without .cs3 */ fileName: String, folder: String ): File? { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/ExtensionsViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/ExtensionsViewModel.kt index b5f82ae8..897e7366 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/ExtensionsViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/ExtensionsViewModel.kt @@ -3,21 +3,19 @@ package com.lagradost.cloudstream3.ui.settings.extensions import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.AcraApplication.Companion.getKey import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.apmap import com.lagradost.cloudstream3.mvvm.Some import com.lagradost.cloudstream3.mvvm.debugAssert -import com.lagradost.cloudstream3.mvvm.launchSafe import com.lagradost.cloudstream3.plugins.PluginManager import com.lagradost.cloudstream3.plugins.PluginManager.getPluginsOnline import com.lagradost.cloudstream3.plugins.RepositoryManager import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIES import com.lagradost.cloudstream3.ui.result.UiText import com.lagradost.cloudstream3.ui.result.txt -import kotlinx.coroutines.launch +import com.lagradost.cloudstream3.utils.Coroutines.ioSafe data class RepositoryData( @JsonProperty("name") val name: String, @@ -46,7 +44,8 @@ class ExtensionsViewModel : ViewModel() { val pluginStats: LiveData> = _pluginStats //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>(REPOSITORIES_KEY) ?: emptyArray()) + PREBUILT_REPOSITORIES @@ -61,6 +60,7 @@ class ExtensionsViewModel : ViewModel() { PluginManager.OnlinePluginData(savedData, onlineData) } }.flatten().distinctBy { it.onlineData.second.url } + val total = onlinePlugins.count() val disabled = outdatedPlugins.count { it.isDisabled } val downloadedTotal = outdatedPlugins.count() diff --git a/app/src/main/res/values-es/array.xml b/app/src/main/res/values-es/array.xml index 489974c5..a9cf3b0f 100644 --- a/app/src/main/res/values-es/array.xml +++ b/app/src/main/res/values-es/array.xml @@ -14,19 +14,6 @@ @id/cast_button_type_forward_30_seconds - - Todos - Películas y TV - Anime - Documental - - - 0 - 1 - 2 - 3 - - @string/resolution_and_title @string/title @@ -223,6 +210,8 @@ Banana Fiesta Dolor rosa + Material You + Material You (Secondary) Normal @@ -242,19 +231,24 @@ Banana Party Pink + Monet + Monet2 + Oscuro Gris Amoled Destello + Material You AmoledLight Black Amoled Light + Monet diff --git a/app/src/main/res/values-pl/array.xml b/app/src/main/res/values-pl/array.xml index efa3da42..cd1b521d 100644 --- a/app/src/main/res/values-pl/array.xml +++ b/app/src/main/res/values-pl/array.xml @@ -219,6 +219,8 @@ Bananowy Łososiowy Świnko peppowy + Material You + Material You (drugorzędny) Normal @@ -238,19 +240,24 @@ Banana Party Pink + Monet + Monet2 + Ciemny Szary Amoled Flashbang + Material You AmoledLight Black Amoled Light + Monet diff --git a/app/src/main/res/values-tr/array.xml b/app/src/main/res/values-tr/array.xml index 747bd6b4..7073a171 100644 --- a/app/src/main/res/values-tr/array.xml +++ b/app/src/main/res/values-tr/array.xml @@ -14,19 +14,6 @@ @id/cast_button_type_forward_30_seconds - - Hepsi - Film ve Dizi - Anime - Belgesel - - - 0 - 1 - 2 - 3 - - @string/resolution_and_title @string/title @@ -223,6 +210,8 @@ Muz Parti Pembe + Material You + Material You (Secondary) Normal @@ -242,19 +231,24 @@ Banana Party Pink + Monet + Monet2 + Koyu Gri Amoled Flaş Bombası + Material You AmoledLight Black Amoled Light + Monet diff --git a/app/src/main/res/values-vi/array.xml b/app/src/main/res/values-vi/array.xml index 27587729..a6181070 100644 --- a/app/src/main/res/values-vi/array.xml +++ b/app/src/main/res/values-vi/array.xml @@ -14,18 +14,6 @@ @id/cast_button_type_forward_30_seconds - - Tất cả - Phim lẻ và Phim bộ - Anime - Phim tài liệu - - - 0 - 1 - 2 - 3 - @string/resolution_and_title @@ -223,6 +211,8 @@ Vàng Hồng Hồng đậm + Material You + Material You (Secondary) Normal @@ -242,19 +232,24 @@ Banana Party Pink + Monet + Monet2 + Tối Xám Amoled Sáng + Material You AmoledLight Black Amoled Light + Monet diff --git a/app/src/main/res/values/array.xml b/app/src/main/res/values/array.xml index e31d86c1..e30ce4e9 100644 --- a/app/src/main/res/values/array.xml +++ b/app/src/main/res/values/array.xml @@ -229,6 +229,8 @@ Banana Party Pink Pain + Material You + Material You (Secondary) Normal @@ -248,6 +250,8 @@ Banana Party Pink + Monet + Monet2 @@ -255,12 +259,14 @@ Gray Amoled Flashbang + Material You AmoledLight Black Amoled Light + Monet diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 842aa326..e771b2e0 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -95,6 +95,16 @@ #000 + + + + + +