Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.dokka)
alias(libs.plugins.kotlin.android)
// alias(libs.plugins.dokka)

// alias(libs.plugins.google.services) // We use manual Firebase initialization
}

val javaTarget = JvmTarget.fromTarget(libs.versions.jvmTarget.get())
Expand Down Expand Up @@ -217,6 +219,18 @@ dependencies {
// Downloading & Networking
implementation(libs.work.runtime.ktx)
implementation(libs.nicehttp) // HTTP Lib

// Firebase
implementation(platform(libs.firebase.bom))
implementation(libs.firebase.firestore)
implementation(libs.firebase.auth)

configurations.all {
resolutionStrategy {
force("com.google.protobuf:protobuf-javalite:3.25.1")
}
exclude(group = "com.google.protobuf", module = "protobuf-java")
}

implementation(project(":library") {
// There does not seem to be a good way of getting the android flavor.
Expand Down Expand Up @@ -269,6 +283,7 @@ tasks.withType<KotlinJvmCompile> {
}
}

/*
dokka {
moduleName = "App"
dokkaSourceSets {
Expand All @@ -287,3 +302,4 @@ dokka {
}
}
}
*/
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package com.lagradost.cloudstream3

import android.content.Context
import com.lagradost.api.setContext
import com.lagradost.cloudstream3.utils.DataStore.getKey
import com.lagradost.cloudstream3.utils.DataStore.removeKeys
import com.lagradost.cloudstream3.utils.DataStore.setKey
import com.lagradost.cloudstream3.utils.getKey
import com.lagradost.cloudstream3.utils.removeKeys
import com.lagradost.cloudstream3.utils.setKey
import java.lang.ref.WeakReference

/**
Expand Down
19 changes: 10 additions & 9 deletions app/src/main/java/com/lagradost/cloudstream3/CloudStreamApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ import com.lagradost.cloudstream3.ui.settings.Globals.TV
import com.lagradost.cloudstream3.ui.settings.Globals.isLayout
import com.lagradost.cloudstream3.utils.AppContextUtils.openBrowser
import com.lagradost.cloudstream3.utils.Coroutines.runOnMainThread
import com.lagradost.cloudstream3.utils.DataStore.getKey
import com.lagradost.cloudstream3.utils.DataStore.getKeys
import com.lagradost.cloudstream3.utils.DataStore.removeKey
import com.lagradost.cloudstream3.utils.DataStore.removeKeys
import com.lagradost.cloudstream3.utils.DataStore.setKey

import com.lagradost.cloudstream3.utils.getKey
import com.lagradost.cloudstream3.utils.getKeys
import com.lagradost.cloudstream3.utils.removeKey
import com.lagradost.cloudstream3.utils.removeKeys
import com.lagradost.cloudstream3.utils.setKey
import com.lagradost.cloudstream3.utils.ImageLoader.buildImageLoader
import kotlinx.coroutines.runBlocking
import java.io.File
Expand Down Expand Up @@ -127,12 +128,12 @@ class CloudStreamApp : Application(), SingletonImageLoader.Factory {
return context?.removeKeys(folder)
}

fun <T> setKey(path: String, value: T) {
context?.setKey(path, value)
fun <T> setKey(path: String, value: T, commit: Boolean = false) {
context?.setKey(path, value, commit)
}

fun <T> setKey(folder: String, path: String, value: T) {
context?.setKey(folder, path, value)
fun <T> setKey(folder: String, path: String, value: T, commit: Boolean = false) {
context?.setKey(folder, path, value, commit)
}

inline fun <reified T : Any> getKey(path: String, defVal: T?): T? {
Expand Down
77 changes: 65 additions & 12 deletions app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import androidx.annotation.IdRes
import androidx.annotation.MainThread
import androidx.appcompat.app.AlertDialog
Expand All @@ -40,6 +42,7 @@ import androidx.core.view.isVisible
import androidx.core.view.marginStart
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.NavDestination
import androidx.navigation.NavDestination.Companion.hierarchy
Expand Down Expand Up @@ -93,6 +96,7 @@ import com.lagradost.cloudstream3.plugins.PluginManager.loadSinglePlugin
import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver
import com.lagradost.cloudstream3.services.SubscriptionWorkManager
import com.lagradost.cloudstream3.syncproviders.AccountManager
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.APP_STRING
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.APP_STRING_PLAYER
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.APP_STRING_REPO
Expand Down Expand Up @@ -138,6 +142,7 @@ import com.lagradost.cloudstream3.utils.AppContextUtils.loadCache
import com.lagradost.cloudstream3.utils.AppContextUtils.loadRepository
import com.lagradost.cloudstream3.utils.AppContextUtils.loadResult
import com.lagradost.cloudstream3.utils.AppContextUtils.loadSearchResult
import com.lagradost.cloudstream3.utils.FirestoreSyncManager
import com.lagradost.cloudstream3.utils.AppContextUtils.setDefaultFocus
import com.lagradost.cloudstream3.utils.AppContextUtils.updateHasTrailers
import com.lagradost.cloudstream3.utils.BackPressedCallbackHelper.attachBackPressedCallback
Expand All @@ -152,8 +157,8 @@ import com.lagradost.cloudstream3.utils.BiometricAuthenticator.promptInfo
import com.lagradost.cloudstream3.utils.BiometricAuthenticator.startBiometricAuthentication
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
import com.lagradost.cloudstream3.utils.Coroutines.main
import com.lagradost.cloudstream3.utils.DataStore.getKey
import com.lagradost.cloudstream3.utils.DataStore.setKey
import com.lagradost.cloudstream3.utils.getKey
import com.lagradost.cloudstream3.utils.setKey
import com.lagradost.cloudstream3.utils.DataStoreHelper
import com.lagradost.cloudstream3.utils.DataStoreHelper.accounts
import com.lagradost.cloudstream3.utils.DataStoreHelper.migrateResumeWatching
Expand Down Expand Up @@ -204,6 +209,8 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa
const val ANIMATED_OUTLINE: Boolean = false
var lastError: String? = null



private const val FILE_DELETE_KEY = "FILES_TO_DELETE_KEY"
const val API_NAME_EXTRA_KEY = "API_NAME_EXTRA_KEY"

Expand Down Expand Up @@ -256,11 +263,18 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa
*/
val reloadLibraryEvent = Event<Boolean>()

/**
* Used by FirestoreSyncManager to notify UI about incoming data changes (e.g. pending plugins)
*/
val syncUpdatedEvent = Event<Boolean>()

/**
* Used by DataStoreHelper to fully reload Navigation Rail header picture
*/
val reloadAccountEvent = Event<Boolean>()



/**
* @return true if the str has launched an app task (be it successful or not)
* @param isWebview does not handle providers and opening download page if true. Can still add repos and login.
Expand Down Expand Up @@ -620,6 +634,9 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa

override fun onResume() {
super.onResume()
if (FirestoreSyncManager.isEnabled(this)) {
ioSafe { FirestoreSyncManager.pushAllLocalData(this@MainActivity) }
}
afterPluginsLoadedEvent += ::onAllPluginsLoaded
setActivityInstance(this)
try {
Expand All @@ -633,7 +650,9 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa

override fun onPause() {
super.onPause()

if (FirestoreSyncManager.isEnabled(this)) {
ioSafe { FirestoreSyncManager.pushAllLocalData(this@MainActivity) }
}
// Start any delayed updates
if (ApkInstaller.delayedInstaller?.startInstallation() == true) {
Toast.makeText(this, R.string.update_started, Toast.LENGTH_LONG).show()
Expand Down Expand Up @@ -821,6 +840,9 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa
}
}
}
// Signal FirestoreSyncManager that plugins are ready,
// so any deferred remote plugin data can be applied safely.
FirestoreSyncManager.onPluginsReady(this@MainActivity)
}
}

Expand Down Expand Up @@ -1191,6 +1213,20 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa
} catch (t: Throwable) {
logError(t)
}



lifecycleScope.launch(Dispatchers.IO) {
FirestoreSyncManager.initialize(this@MainActivity)
}

afterPluginsLoadedEvent += {
FirestoreSyncManager.onPluginsReady(this)
}

mainPluginsLoadedEvent += {
FirestoreSyncManager.onPluginsReady(this)
}

window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
updateTv()
Expand Down Expand Up @@ -1349,6 +1385,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa
)
} else {
___DO_NOT_CALL_FROM_A_PLUGIN_loadAllOnlinePlugins(this@MainActivity)
afterPluginsLoadedEvent.invoke(false)
}

//Automatically download not existing plugins, using mode specified.
Expand All @@ -1358,19 +1395,31 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa
0
)
) ?: AutoDownloadMode.Disable
if (autoDownloadPlugin != AutoDownloadMode.Disable) {
PluginManager.___DO_NOT_CALL_FROM_A_PLUGIN_downloadNotExistingPluginsAndLoad(
this@MainActivity,
autoDownloadPlugin
)
try {
if (autoDownloadPlugin != AutoDownloadMode.Disable) {
PluginManager.___DO_NOT_CALL_FROM_A_PLUGIN_downloadNotExistingPluginsAndLoad(
this@MainActivity,
autoDownloadPlugin
)
}
} catch (e: Exception) {
main { showToast(txt("Online Plugin Load Failed: ${e.message}"), Toast.LENGTH_LONG) }
e.printStackTrace()
}
main { FirestoreSyncManager.onPluginsReady(this@MainActivity) }
}

ioSafe {
PluginManager.___DO_NOT_CALL_FROM_A_PLUGIN_loadAllLocalPlugins(
this@MainActivity,
false
)
try {
PluginManager.___DO_NOT_CALL_FROM_A_PLUGIN_loadAllLocalPlugins(
this@MainActivity,
false
)
} catch (e: Exception) {
main { showToast(txt("Local Plugin Load Failed: ${e.message}"), Toast.LENGTH_LONG) }
e.printStackTrace()
}
main { FirestoreSyncManager.onPluginsReady(this@MainActivity) }
}

// Add your channel creation here
Expand Down Expand Up @@ -1653,6 +1702,9 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa
val navController = navHostFragment.navController

navController.addOnDestinationChangedListener { _: NavController, navDestination: NavDestination, bundle: Bundle? ->
if (FirestoreSyncManager.isEnabled(this@MainActivity)) {
FirestoreSyncManager.syncNow(this@MainActivity)
}
// Intercept search and add a query
updateNavBar(navDestination)
if (navDestination.matchDestination(R.id.navigation_search) && !nextSearchQuery.isNullOrBlank()) {
Expand Down Expand Up @@ -2032,6 +2084,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa
updateLocale()
runDefault()
}

}

/** Biometric stuff **/
Expand Down
Loading