diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt index bea1a2b9..98e6088a 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt @@ -35,6 +35,7 @@ import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver import com.lagradost.cloudstream3.ui.APIRepository 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.DataStore.getKey import com.lagradost.cloudstream3.utils.DataStore.removeKey @@ -117,14 +118,26 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { override fun onResume() { super.onResume() - mCastSession = mSessionManager.currentCastSession - mSessionManager.addSessionManagerListener(mSessionManagerListener) + try { + if(isCastApiAvailable()) { + mCastSession = mSessionManager.currentCastSession + mSessionManager.addSessionManagerListener(mSessionManagerListener) + } + } catch (e : Exception) { + logError(e) + } } override fun onPause() { super.onPause() - mSessionManager.removeSessionManagerListener(mSessionManagerListener) - mCastSession = null + try { + if(isCastApiAvailable()) { + mSessionManager.removeSessionManagerListener(mSessionManagerListener) + mCastSession = null + } + } catch (e : Exception) { + logError(e) + } } companion object { @@ -188,7 +201,6 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { fun Context.updateLocale() { val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) val localeCode = settingsManager.getString(getString(R.string.locale_key), null) - println("LOCALE: " + 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() { this.updateLocale() - if (backPressed()) return + backEvent.invoke(true) super.onBackPressed() 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 updateLocale() super.onCreate(savedInstanceState) - mSessionManager = CastContext.getSharedInstance(this).sessionManager + try { + if(isCastApiAvailable()) { + mSessionManager = CastContext.getSharedInstance(this).sessionManager + } + } catch (e : Exception) { + logError(e) + } window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN) diff --git a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/AllMoviesForYouProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/AllMoviesForYouProvider.kt index 568d0570..7a1b7e6e 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/AllMoviesForYouProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/AllMoviesForYouProvider.kt @@ -7,6 +7,8 @@ import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.Jsoup import org.jsoup.nodes.Document +import java.lang.Thread.sleep +import java.net.URLDecoder class AllMoviesForYouProvider : MainAPI() { companion object { @@ -79,7 +81,7 @@ class AllMoviesForYouProvider : MainAPI() { document.selectFirst("div.Vote > div.post-ratings > span")?.text()?.toFloatOrNull()?.times(10)?.toInt() val year = document.selectFirst("span.Date")?.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) { val list = ArrayList>() @@ -142,7 +144,7 @@ class AllMoviesForYouProvider : MainAPI() { url, this.name, type, - mapper.writeValueAsString(data), + mapper.writeValueAsString(data.filter { it != "about:blank" }), backgroundPoster, year?.toIntOrNull(), descipt, @@ -170,9 +172,43 @@ class AllMoviesForYouProvider : MainAPI() { } return false } 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")) { - callback(ExtractorLink(this.name, this.name, realDataUrl, mainUrl, Qualities.Unknown.value)) + 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)) + } return true } val response = khttp.get(realDataUrl) @@ -188,4 +224,4 @@ class AllMoviesForYouProvider : MainAPI() { return true } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt index 88f8d664..64fc88e0 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt @@ -14,7 +14,6 @@ import android.widget.TextView import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels -import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import com.google.android.material.bottomsheet.BottomSheetDialog diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt index e36badaa..b42ed875 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt @@ -53,6 +53,7 @@ class HomeViewModel : ViewModel() { val resumeWatching: LiveData> = _resumeWatching fun loadResumeWatching(context: Context) = viewModelScope.launch { + println("Resume::") val resumeWatching = withContext(Dispatchers.IO) { context.getAllResumeStateIds().mapNotNull { id -> context.getLastWatched(id) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt index e0f90536..3beefae1 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt @@ -70,10 +70,7 @@ import com.lagradost.cloudstream3.MainActivity.Companion.canEnterPipMode import com.lagradost.cloudstream3.MainActivity.Companion.isInPIPMode import com.lagradost.cloudstream3.MainActivity.Companion.showToast import com.lagradost.cloudstream3.R -import com.lagradost.cloudstream3.mvvm.Resource -import com.lagradost.cloudstream3.mvvm.normalSafeApiCall -import com.lagradost.cloudstream3.mvvm.observe -import com.lagradost.cloudstream3.mvvm.observeDirectly +import com.lagradost.cloudstream3.mvvm.* import com.lagradost.cloudstream3.ui.result.ResultEpisode import com.lagradost.cloudstream3.ui.result.ResultViewModel import com.lagradost.cloudstream3.ui.subtitles.SaveCaptionStyle @@ -1046,79 +1043,83 @@ class PlayerFragment : Fragment() { }*/ if (activity?.isCastApiAvailable() == true && !isDownloadedFile) { - CastButtonFactory.setUpMediaRouteButton(activity, player_media_route_button) - val castContext = CastContext.getSharedInstance(requireContext()) + try { + CastButtonFactory.setUpMediaRouteButton(activity, player_media_route_button) + val castContext = CastContext.getSharedInstance(requireContext()) - if (castContext.castState != CastState.NO_DEVICES_AVAILABLE) player_media_route_button.visibility = VISIBLE - castContext.addCastStateListener { state -> - if (player_media_route_button != null) { - player_media_route_button.isVisible = state != CastState.NO_DEVICES_AVAILABLE + if (castContext.castState != CastState.NO_DEVICES_AVAILABLE) player_media_route_button.visibility = VISIBLE + castContext.addCastStateListener { state -> + if (player_media_route_button != null) { + player_media_route_button.isVisible = state != CastState.NO_DEVICES_AVAILABLE - if (state == CastState.CONNECTED) { - if (!this::exoPlayer.isInitialized) return@addCastStateListener - val links = sortUrls(getUrls() ?: return@addCastStateListener) - val epData = getEpisode() ?: return@addCastStateListener + if (state == CastState.CONNECTED) { + if (!this::exoPlayer.isInitialized) return@addCastStateListener + val links = sortUrls(getUrls() ?: return@addCastStateListener) + val epData = getEpisode() ?: return@addCastStateListener - val index = links.indexOf(getCurrentUrl()) - (activity as MainActivity?)?.mCastSession?.startCast( - apiName, - currentIsMovie ?: return@addCastStateListener, - currentHeaderName, - currentPoster, - epData.index, - episodes, - links, - context?.getSubs(supportsDownloadedFiles = false) ?: emptyList(), - index, - exoPlayer.currentPosition - ) + val index = links.indexOf(getCurrentUrl()) + (activity as MainActivity?)?.mCastSession?.startCast( + apiName, + currentIsMovie ?: return@addCastStateListener, + currentHeaderName, + currentPoster, + epData.index, + episodes, + links, + context?.getSubs(supportsDownloadedFiles = false) ?: emptyList(), + index, + exoPlayer.currentPosition + ) - /* - val customData = - links.map { JSONObject().put("name", it.name) } - val jsonArray = JSONArray() - for (item in customData) { - jsonArray.put(item) - } - - val mediaItems = links.map { - val movieMetadata = MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE) - - movieMetadata.putString(MediaMetadata.KEY_SUBTITLE, - epData.name ?: "Episode ${epData.episode}") - - if (currentHeaderName != null) - movieMetadata.putString(MediaMetadata.KEY_TITLE, currentHeaderName) - - val srcPoster = epData.poster ?: currentPoster - if (srcPoster != null) { - movieMetadata.addImage(WebImage(Uri.parse(srcPoster))) + /* + val customData = + links.map { JSONObject().put("name", it.name) } + val jsonArray = JSONArray() + for (item in customData) { + jsonArray.put(item) } - MediaQueueItem.Builder( - MediaInfo.Builder(it.url) - .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED) - .setContentType(MimeTypes.VIDEO_UNKNOWN) + val mediaItems = links.map { + val movieMetadata = MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE) - .setCustomData(JSONObject().put("data", jsonArray)) - .setMetadata(movieMetadata) + movieMetadata.putString(MediaMetadata.KEY_SUBTITLE, + epData.name ?: "Episode ${epData.episode}") + + if (currentHeaderName != null) + movieMetadata.putString(MediaMetadata.KEY_TITLE, currentHeaderName) + + val srcPoster = epData.poster ?: currentPoster + if (srcPoster != null) { + movieMetadata.addImage(WebImage(Uri.parse(srcPoster))) + } + + MediaQueueItem.Builder( + MediaInfo.Builder(it.url) + .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED) + .setContentType(MimeTypes.VIDEO_UNKNOWN) + + .setCustomData(JSONObject().put("data", jsonArray)) + .setMetadata(movieMetadata) + .build() + ) .build() - ) - .build() - }.toTypedArray() + }.toTypedArray() - val castPlayer = CastPlayer(castContext) - castPlayer.loadItems( - mediaItems, - if (index > 0) index else 0, - exoPlayer.currentPosition, - MediaStatus.REPEAT_MODE_REPEAT_SINGLE - )*/ - // activity?.popCurrentPage(isInPlayer = true, isInExpandedView = false, isInResults = false) - safeReleasePlayer() - activity?.popCurrentPage() + val castPlayer = CastPlayer(castContext) + castPlayer.loadItems( + mediaItems, + if (index > 0) index else 0, + exoPlayer.currentPosition, + MediaStatus.REPEAT_MODE_REPEAT_SINGLE + )*/ + // activity?.popCurrentPage(isInPlayer = true, isInExpandedView = false, isInResults = false) + safeReleasePlayer() + activity?.popCurrentPage() + } } } + } catch (e : Exception) { + logError(e) } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt index 68de7dfc..13bf82e8 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt @@ -17,7 +17,6 @@ import android.view.View.VISIBLE import android.view.ViewGroup import android.widget.Toast import androidx.appcompat.app.AlertDialog -import androidx.appcompat.app.AppCompatActivity import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.content.ContextCompat import androidx.core.content.FileProvider @@ -37,8 +36,8 @@ import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.APIHolder.getApiFromName import com.lagradost.cloudstream3.APIHolder.getId 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.logError import com.lagradost.cloudstream3.mvvm.observe import com.lagradost.cloudstream3.ui.WatchType import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD @@ -304,16 +303,20 @@ class ResultFragment : Fragment() { activity?.let { if (it.isCastApiAvailable()) { - CastButtonFactory.setUpMediaRouteButton(it, media_route_button) - val castContext = CastContext.getSharedInstance(it.applicationContext) + try { + CastButtonFactory.setUpMediaRouteButton(it, media_route_button) + val castContext = CastContext.getSharedInstance(it.applicationContext) - if (castContext.castState != CastState.NO_DEVICES_AVAILABLE) media_route_button.visibility = VISIBLE - castContext.addCastStateListener { state -> - if (media_route_button != null) { - if (state == CastState.NO_DEVICES_AVAILABLE) media_route_button.visibility = GONE else { - if (media_route_button.visibility == GONE) media_route_button.visibility = VISIBLE + if (castContext.castState != CastState.NO_DEVICES_AVAILABLE) media_route_button.visibility = VISIBLE + castContext.addCastStateListener { state -> + if (media_route_button != null) { + if (state == CastState.NO_DEVICES_AVAILABLE) media_route_button.visibility = GONE else { + if (media_route_button.visibility == GONE) media_route_button.visibility = VISIBLE + } } } + } catch (e : Exception) { + logError(e) } } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt index 828ea4e6..223de62b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt @@ -110,16 +110,23 @@ class SettingsFragment : PreferenceFragmentCompat() { 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( - names, + names.map { it.second }, currentList, getString(R.string.provider_lang_settings), {}) { selectedList -> settingsManager.edit().putStringSet( this.getString(R.string.provider_lang_key), - selectedList.map { names[it] }.toMutableSet() + selectedList.map { names[it].first }.toMutableSet() ).apply() } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt index f674c307..29799864 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt @@ -260,7 +260,7 @@ object VideoDownloadManager { } 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 ""