mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
20eafc2e89
8 changed files with 157 additions and 126 deletions
|
@ -35,6 +35,7 @@ import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver
|
import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver
|
||||||
import com.lagradost.cloudstream3.ui.APIRepository
|
import com.lagradost.cloudstream3.ui.APIRepository
|
||||||
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO
|
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.loadResult
|
import com.lagradost.cloudstream3.utils.AppUtils.loadResult
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.removeKey
|
import com.lagradost.cloudstream3.utils.DataStore.removeKey
|
||||||
|
@ -117,15 +118,27 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
try {
|
||||||
|
if(isCastApiAvailable()) {
|
||||||
mCastSession = mSessionManager.currentCastSession
|
mCastSession = mSessionManager.currentCastSession
|
||||||
mSessionManager.addSessionManagerListener(mSessionManagerListener)
|
mSessionManager.addSessionManagerListener(mSessionManagerListener)
|
||||||
}
|
}
|
||||||
|
} catch (e : Exception) {
|
||||||
|
logError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
|
try {
|
||||||
|
if(isCastApiAvailable()) {
|
||||||
mSessionManager.removeSessionManagerListener(mSessionManagerListener)
|
mSessionManager.removeSessionManagerListener(mSessionManagerListener)
|
||||||
mCastSession = null
|
mCastSession = null
|
||||||
}
|
}
|
||||||
|
} catch (e : Exception) {
|
||||||
|
logError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
var canEnterPipMode: Boolean = false
|
var canEnterPipMode: Boolean = false
|
||||||
|
@ -188,7 +201,6 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
fun Context.updateLocale() {
|
fun Context.updateLocale() {
|
||||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
val localeCode = settingsManager.getString(getString(R.string.locale_key), null)
|
val localeCode = settingsManager.getString(getString(R.string.locale_key), null)
|
||||||
println("LOCALE: " + localeCode)
|
|
||||||
setLocale(this, localeCode)
|
setLocale(this, localeCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,43 +231,9 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun AppCompatActivity.backPressed(): Boolean {
|
|
||||||
/*val currentFragment = supportFragmentManager.fragments.last {
|
|
||||||
it.isVisible
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentFragment is NavHostFragment) {
|
|
||||||
val child = currentFragment.childFragmentManager.fragments.last {
|
|
||||||
it.isVisible
|
|
||||||
}
|
|
||||||
if (child is DownloadChildFragment) {
|
|
||||||
val navController = findNavController(R.id.nav_host_fragment)
|
|
||||||
navController.navigate(R.id.navigation_downloads, Bundle(), navOptions)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if (child is SearchFragment || child is HomeFragment || child is DownloadFragment || child is SettingsFragment) {
|
|
||||||
this.finish()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentFragment != null && supportFragmentManager.fragments.size > 2) {
|
|
||||||
//MainActivity.showNavbar()
|
|
||||||
supportFragmentManager.beginTransaction()
|
|
||||||
.setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim, R.anim.pop_enter, R.anim.pop_exit)
|
|
||||||
.remove(currentFragment)
|
|
||||||
.commitAllowingStateLoss()
|
|
||||||
backEvent.invoke(true)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
backEvent.invoke(false)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed() {
|
override fun onBackPressed() {
|
||||||
this.updateLocale()
|
this.updateLocale()
|
||||||
if (backPressed()) return
|
backEvent.invoke(true)
|
||||||
super.onBackPressed()
|
super.onBackPressed()
|
||||||
this.updateLocale()
|
this.updateLocale()
|
||||||
}
|
}
|
||||||
|
@ -315,7 +293,13 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
) // THEME IS SET BEFORE VIEW IS CREATED TO APPLY THE THEME TO THE MAIN VIEW
|
) // THEME IS SET BEFORE VIEW IS CREATED TO APPLY THE THEME TO THE MAIN VIEW
|
||||||
updateLocale()
|
updateLocale()
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
try {
|
||||||
|
if(isCastApiAvailable()) {
|
||||||
mSessionManager = CastContext.getSharedInstance(this).sessionManager
|
mSessionManager = CastContext.getSharedInstance(this).sessionManager
|
||||||
|
}
|
||||||
|
} catch (e : Exception) {
|
||||||
|
logError(e)
|
||||||
|
}
|
||||||
|
|
||||||
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
|
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@ import com.lagradost.cloudstream3.utils.Qualities
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
|
import java.lang.Thread.sleep
|
||||||
|
import java.net.URLDecoder
|
||||||
|
|
||||||
class AllMoviesForYouProvider : MainAPI() {
|
class AllMoviesForYouProvider : MainAPI() {
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -79,7 +81,7 @@ class AllMoviesForYouProvider : MainAPI() {
|
||||||
document.selectFirst("div.Vote > div.post-ratings > span")?.text()?.toFloatOrNull()?.times(10)?.toInt()
|
document.selectFirst("div.Vote > div.post-ratings > span")?.text()?.toFloatOrNull()?.times(10)?.toInt()
|
||||||
val year = document.selectFirst("span.Date")?.text()
|
val year = document.selectFirst("span.Date")?.text()
|
||||||
val duration = document.selectFirst("span.Time").text()
|
val duration = document.selectFirst("span.Time").text()
|
||||||
val backgroundPoster = fixUrl(document.selectFirst("div.Image > figure > img").attr("src"))
|
val backgroundPoster = fixUrl(document.selectFirst("div.Image > figure > img").attr("data-src"))
|
||||||
|
|
||||||
if (type == TvType.TvSeries) {
|
if (type == TvType.TvSeries) {
|
||||||
val list = ArrayList<Pair<Int, String>>()
|
val list = ArrayList<Pair<Int, String>>()
|
||||||
|
@ -142,7 +144,7 @@ class AllMoviesForYouProvider : MainAPI() {
|
||||||
url,
|
url,
|
||||||
this.name,
|
this.name,
|
||||||
type,
|
type,
|
||||||
mapper.writeValueAsString(data),
|
mapper.writeValueAsString(data.filter { it != "about:blank" }),
|
||||||
backgroundPoster,
|
backgroundPoster,
|
||||||
year?.toIntOrNull(),
|
year?.toIntOrNull(),
|
||||||
descipt,
|
descipt,
|
||||||
|
@ -170,9 +172,43 @@ class AllMoviesForYouProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
} else if (data.startsWith(mainUrl) && data != mainUrl) {
|
} else if (data.startsWith(mainUrl) && data != mainUrl) {
|
||||||
val realDataUrl = data.replace("&", "&").replace("&", "&")
|
val realDataUrl = URLDecoder.decode(data, "application/x-www-form-urlencoded")
|
||||||
if (data.contains("trdownload")) {
|
if (data.contains("trdownload")) {
|
||||||
|
val request = khttp.get(data, stream = true)
|
||||||
|
if (request.url.startsWith("https://streamhub.to/d/")) {
|
||||||
|
val document = Jsoup.parse(request.text)
|
||||||
|
val inputs = document.select("Form > input")
|
||||||
|
if (inputs.size < 4) return false
|
||||||
|
var op: String? = null
|
||||||
|
var id: String? = null
|
||||||
|
var mode: String? = null
|
||||||
|
var hash: String? = null
|
||||||
|
|
||||||
|
for (input in inputs) {
|
||||||
|
val value = input.attr("value") ?: continue
|
||||||
|
when (input.attr("name")) {
|
||||||
|
"op" -> op = value
|
||||||
|
"id" -> id = value
|
||||||
|
"mode" -> mode = value
|
||||||
|
"hash" -> hash = value
|
||||||
|
else -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(op == null || id == null || mode == null || hash == null) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
sleep(5000) // ye this is needed, wont work with 0 delay
|
||||||
|
|
||||||
|
val postResponse = khttp.post(request.url, headers = mapOf("content-type" to "application/x-www-form-urlencoded", "referer" to request.url, "user-agent" to USER_AGENT, "accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"), data = mapOf("op" to op, "id" to id, "mode" to mode, "hash" to hash))
|
||||||
|
val postDocument = Jsoup.parse(postResponse.text)
|
||||||
|
|
||||||
|
val url = postDocument.selectFirst("a.downloadbtn").attr("href")
|
||||||
|
if(url.isNullOrEmpty()) return false
|
||||||
|
callback(ExtractorLink(this.name, this.name, url, mainUrl, Qualities.Unknown.value))
|
||||||
|
} else {
|
||||||
callback(ExtractorLink(this.name, this.name, realDataUrl, mainUrl, Qualities.Unknown.value))
|
callback(ExtractorLink(this.name, this.name, realDataUrl, mainUrl, Qualities.Unknown.value))
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
val response = khttp.get(realDataUrl)
|
val response = khttp.get(realDataUrl)
|
||||||
|
|
|
@ -14,7 +14,6 @@ import android.widget.TextView
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
|
|
|
@ -53,6 +53,7 @@ class HomeViewModel : ViewModel() {
|
||||||
val resumeWatching: LiveData<List<SearchResponse>> = _resumeWatching
|
val resumeWatching: LiveData<List<SearchResponse>> = _resumeWatching
|
||||||
|
|
||||||
fun loadResumeWatching(context: Context) = viewModelScope.launch {
|
fun loadResumeWatching(context: Context) = viewModelScope.launch {
|
||||||
|
println("Resume::")
|
||||||
val resumeWatching = withContext(Dispatchers.IO) {
|
val resumeWatching = withContext(Dispatchers.IO) {
|
||||||
context.getAllResumeStateIds().mapNotNull { id ->
|
context.getAllResumeStateIds().mapNotNull { id ->
|
||||||
context.getLastWatched(id)
|
context.getLastWatched(id)
|
||||||
|
|
|
@ -70,10 +70,7 @@ import com.lagradost.cloudstream3.MainActivity.Companion.canEnterPipMode
|
||||||
import com.lagradost.cloudstream3.MainActivity.Companion.isInPIPMode
|
import com.lagradost.cloudstream3.MainActivity.Companion.isInPIPMode
|
||||||
import com.lagradost.cloudstream3.MainActivity.Companion.showToast
|
import com.lagradost.cloudstream3.MainActivity.Companion.showToast
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.mvvm.Resource
|
import com.lagradost.cloudstream3.mvvm.*
|
||||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
|
||||||
import com.lagradost.cloudstream3.mvvm.observeDirectly
|
|
||||||
import com.lagradost.cloudstream3.ui.result.ResultEpisode
|
import com.lagradost.cloudstream3.ui.result.ResultEpisode
|
||||||
import com.lagradost.cloudstream3.ui.result.ResultViewModel
|
import com.lagradost.cloudstream3.ui.result.ResultViewModel
|
||||||
import com.lagradost.cloudstream3.ui.subtitles.SaveCaptionStyle
|
import com.lagradost.cloudstream3.ui.subtitles.SaveCaptionStyle
|
||||||
|
@ -1046,6 +1043,7 @@ class PlayerFragment : Fragment() {
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
if (activity?.isCastApiAvailable() == true && !isDownloadedFile) {
|
if (activity?.isCastApiAvailable() == true && !isDownloadedFile) {
|
||||||
|
try {
|
||||||
CastButtonFactory.setUpMediaRouteButton(activity, player_media_route_button)
|
CastButtonFactory.setUpMediaRouteButton(activity, player_media_route_button)
|
||||||
val castContext = CastContext.getSharedInstance(requireContext())
|
val castContext = CastContext.getSharedInstance(requireContext())
|
||||||
|
|
||||||
|
@ -1120,6 +1118,9 @@ class PlayerFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (e : Exception) {
|
||||||
|
logError(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isDownloadedFile = false
|
isDownloadedFile = false
|
||||||
|
|
|
@ -17,7 +17,6 @@ import android.view.View.VISIBLE
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
|
@ -37,8 +36,8 @@ import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.APIHolder.getApiFromName
|
import com.lagradost.cloudstream3.APIHolder.getApiFromName
|
||||||
import com.lagradost.cloudstream3.APIHolder.getId
|
import com.lagradost.cloudstream3.APIHolder.getId
|
||||||
import com.lagradost.cloudstream3.MainActivity.Companion.showToast
|
import com.lagradost.cloudstream3.MainActivity.Companion.showToast
|
||||||
import com.lagradost.cloudstream3.MainActivity.Companion.updateLocale
|
|
||||||
import com.lagradost.cloudstream3.mvvm.Resource
|
import com.lagradost.cloudstream3.mvvm.Resource
|
||||||
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
import com.lagradost.cloudstream3.ui.WatchType
|
import com.lagradost.cloudstream3.ui.WatchType
|
||||||
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD
|
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD
|
||||||
|
@ -304,6 +303,7 @@ class ResultFragment : Fragment() {
|
||||||
|
|
||||||
activity?.let {
|
activity?.let {
|
||||||
if (it.isCastApiAvailable()) {
|
if (it.isCastApiAvailable()) {
|
||||||
|
try {
|
||||||
CastButtonFactory.setUpMediaRouteButton(it, media_route_button)
|
CastButtonFactory.setUpMediaRouteButton(it, media_route_button)
|
||||||
val castContext = CastContext.getSharedInstance(it.applicationContext)
|
val castContext = CastContext.getSharedInstance(it.applicationContext)
|
||||||
|
|
||||||
|
@ -315,6 +315,9 @@ class ResultFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (e : Exception) {
|
||||||
|
logError(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,16 +110,23 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
currentList.add(allLangs.indexOf(i))
|
currentList.add(allLangs.indexOf(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
val names = allLangs.mapNotNull { SubtitleHelper.fromTwoLettersToLanguage(it) }
|
val names = allLangs.mapNotNull {
|
||||||
|
val fullName = SubtitleHelper.fromTwoLettersToLanguage(it)
|
||||||
|
if (fullName.isNullOrEmpty()) {
|
||||||
|
return@mapNotNull null
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair(it, fullName)
|
||||||
|
}
|
||||||
|
|
||||||
context?.showMultiDialog(
|
context?.showMultiDialog(
|
||||||
names,
|
names.map { it.second },
|
||||||
currentList,
|
currentList,
|
||||||
getString(R.string.provider_lang_settings),
|
getString(R.string.provider_lang_settings),
|
||||||
{}) { selectedList ->
|
{}) { selectedList ->
|
||||||
settingsManager.edit().putStringSet(
|
settingsManager.edit().putStringSet(
|
||||||
this.getString(R.string.provider_lang_key),
|
this.getString(R.string.provider_lang_key),
|
||||||
selectedList.map { names[it] }.toMutableSet()
|
selectedList.map { names[it].first }.toMutableSet()
|
||||||
).apply()
|
).apply()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,7 +260,7 @@ object VideoDownloadManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == DownloadType.IsDownloading || state == DownloadType.IsPaused) {
|
if (state == DownloadType.IsDownloading || state == DownloadType.IsPaused) {
|
||||||
builder.setProgress(total.toInt(), progress.toInt(), false)
|
builder.setProgress((total / 1000).toInt(), (progress / 1000).toInt(), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
val rowTwoExtra = if (ep.name != null) " - ${ep.name}\n" else ""
|
val rowTwoExtra = if (ep.name != null) " - ${ep.name}\n" else ""
|
||||||
|
|
Loading…
Reference in a new issue