play any stream & a bit of work on invideoplayer episodes & no links found last error

This commit is contained in:
LagradOst 2022-07-17 02:41:01 +02:00
parent bb7400638a
commit e7e63b4855
17 changed files with 585 additions and 528 deletions

View file

@ -36,7 +36,7 @@ android {
targetSdkVersion 30 targetSdkVersion 30
versionCode 48 versionCode 48
versionName "2.10.30" versionName "2.10.31"
resValue "string", "app_version", resValue "string", "app_version",
"${defaultConfig.versionName}${versionNameSuffix ?: ""}" "${defaultConfig.versionName}${versionNameSuffix ?: ""}"

View file

@ -8,7 +8,7 @@ import com.lagradost.cloudstream3.utils.loadExtractor
import org.jsoup.Jsoup import org.jsoup.Jsoup
class HDMovie5 : MainAPI() { class HDMovie5 : MainAPI() {
override var mainUrl = "https://hdmovie2.org" override var mainUrl = "https://Hdmovie2.biz"
override var name = "HDMovie" override var name = "HDMovie"
override var lang = "hi" override var lang = "hi"

View file

@ -2,8 +2,11 @@ package com.lagradost.cloudstream3.movieproviders
import android.util.Log import android.util.Log
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.APIHolder.getCaptchaToken import com.lagradost.cloudstream3.APIHolder.getCaptchaToken
import com.lagradost.cloudstream3.SubtitleFile
import com.lagradost.cloudstream3.TvType
import com.lagradost.cloudstream3.apmap
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.metaproviders.TmdbLink import com.lagradost.cloudstream3.metaproviders.TmdbLink
import com.lagradost.cloudstream3.metaproviders.TmdbProvider import com.lagradost.cloudstream3.metaproviders.TmdbProvider
import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.extractRabbitStream import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.extractRabbitStream
@ -15,7 +18,7 @@ import com.lagradost.cloudstream3.utils.loadExtractor
class TwoEmbedProvider : TmdbProvider() { class TwoEmbedProvider : TmdbProvider() {
override val apiName = "2Embed" override val apiName = "2Embed"
override var name = "2Embed" override var name = "2Embed"
override var mainUrl = "https://www.2embed.to" override var mainUrl = "https://www.2embed.org"
override val useMetaLoadResponse = true override val useMetaLoadResponse = true
override val instantLinkLoading = false override val instantLinkLoading = false
override val supportedTypes = setOf( override val supportedTypes = setOf(

View file

@ -12,21 +12,40 @@ import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.utils.UIHelper.adjustAlpha import com.lagradost.cloudstream3.utils.UIHelper.adjustAlpha
import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute
import com.lagradost.cloudstream3.utils.UIHelper.toPx import com.lagradost.cloudstream3.utils.UIHelper.toPx
import java.lang.ref.WeakReference
class MyMiniControllerFragment : MiniControllerFragment() { class MyMiniControllerFragment : MiniControllerFragment() {
var currentColor: Int = 0 var currentColor: Int = 0
// I KNOW, KINDA SPAGHETTI SOLUTION, BUT IT WORKS override fun onDestroy() {
override fun onInflate(context: Context, attributeSet: AttributeSet, bundle: Bundle?) { currentColor = 0
val obtainStyledAttributes = context.obtainStyledAttributes(attributeSet, R.styleable.CustomCast, 0, 0) super.onDestroy()
if (obtainStyledAttributes.hasValue(R.styleable.CustomCast_customCastBackgroundColor)) {
currentColor = obtainStyledAttributes.getColor(R.styleable.CustomCast_customCastBackgroundColor, 0)
}
obtainStyledAttributes.recycle()
super.onInflate(context, attributeSet, bundle)
} }
// I KNOW, KINDA SPAGHETTI SOLUTION, BUT IT WORKS
override fun onInflate(context: Context, attributeSet: AttributeSet, bundle: Bundle?) {
super.onInflate(context, attributeSet, bundle)
// somehow this leaks and I really dont know why, it seams like if you go back to a fragment with this, it leaks????
if (currentColor == 0) {
WeakReference(
context.obtainStyledAttributes(
attributeSet,
R.styleable.CustomCast
)
).apply {
if (get()
?.hasValue(R.styleable.CustomCast_customCastBackgroundColor) == true
) {
currentColor =
get()
?.getColor(R.styleable.CustomCast_customCastBackgroundColor, 0) ?: 0
}
get()?.recycle()
}.clear()
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -38,18 +57,24 @@ class MyMiniControllerFragment : MiniControllerFragment() {
val containerCurrent: RelativeLayout? = view.findViewById(R.id.container_current) val containerCurrent: RelativeLayout? = view.findViewById(R.id.container_current)
context?.let { ctx -> context?.let { ctx ->
progressBar?.setBackgroundColor(adjustAlpha(ctx.colorFromAttribute(R.attr.colorPrimary), 0.35f)) progressBar?.setBackgroundColor(
val params = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, 2.toPx) adjustAlpha(
ctx.colorFromAttribute(R.attr.colorPrimary),
0.35f
)
)
val params = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
2.toPx
)
progressBar?.layoutParams = params progressBar?.layoutParams = params
val color = currentColor
if (currentColor != 0) { if (color != 0)
containerCurrent?.setBackgroundColor(currentColor) containerCurrent?.setBackgroundColor(color)
}
} }
val child = containerAll?.getChildAt(0) val child = containerAll?.getChildAt(0)
child?.alpha = 0f // REMOVE GRADIENT child?.alpha = 0f // REMOVE GRADIENT
} catch (e: Exception) { } catch (e: Exception) {
// JUST IN CASE // JUST IN CASE
} }

View file

@ -31,12 +31,8 @@ class DownloadChildFragment : Fragment() {
override fun onDestroyView() { override fun onDestroyView() {
(download_child_list?.adapter as DownloadChildAdapter?)?.killAdapter() (download_child_list?.adapter as DownloadChildAdapter?)?.killAdapter()
super.onDestroyView()
}
override fun onDestroy() {
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent -= it } downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent -= it }
super.onDestroy() super.onDestroyView()
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

View file

@ -65,16 +65,12 @@ class DownloadFragment : Fragment() {
} }
override fun onDestroyView() { override fun onDestroyView() {
(download_list?.adapter as DownloadHeaderAdapter?)?.killAdapter()
super.onDestroyView()
}
override fun onDestroy() {
if (downloadDeleteEventListener != null) { if (downloadDeleteEventListener != null) {
VideoDownloadManager.downloadDeleteEvent -= downloadDeleteEventListener!! VideoDownloadManager.downloadDeleteEvent -= downloadDeleteEventListener!!
downloadDeleteEventListener = null downloadDeleteEventListener = null
} }
super.onDestroy() (download_list?.adapter as DownloadHeaderAdapter?)?.killAdapter()
super.onDestroyView()
} }
override fun onCreateView( override fun onCreateView(
@ -83,7 +79,17 @@ class DownloadFragment : Fragment() {
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
downloadsViewModel = downloadsViewModel =
ViewModelProvider(this).get(DownloadViewModel::class.java) ViewModelProvider(this)[DownloadViewModel::class.java]
return inflater.inflate(R.layout.fragment_downloads, container, false)
}
private var downloadDeleteEventListener: ((Int) -> Unit)? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
hideKeyboard()
observe(downloadsViewModel.noDownloadsText) { observe(downloadsViewModel.noDownloadsText) {
text_no_downloads.text = it text_no_downloads.text = it
} }
@ -114,16 +120,8 @@ class DownloadFragment : Fragment() {
getBytesAsText(it) getBytesAsText(it)
) )
download_app?.setLayoutWidth(it) download_app?.setLayoutWidth(it)
download_storage_appbar?.visibility = View.VISIBLE download_storage_appbar?.isVisible = it > 0
} }
return inflater.inflate(R.layout.fragment_downloads, container, false)
}
private var downloadDeleteEventListener: ((Int) -> Unit)? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
hideKeyboard()
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> = val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> =
DownloadHeaderAdapter( DownloadHeaderAdapter(

View file

@ -8,6 +8,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.lagradost.cloudstream3.isMovieType import com.lagradost.cloudstream3.isMovieType
import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.utils.DOWNLOAD_EPISODE_CACHE import com.lagradost.cloudstream3.utils.DOWNLOAD_EPISODE_CACHE
import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE
import com.lagradost.cloudstream3.utils.DataStore.getFolderName import com.lagradost.cloudstream3.utils.DataStore.getFolderName
@ -100,16 +101,20 @@ class DownloadViewModel : ViewModel() {
(it.child?.episode ?: 0) + (it.child?.season?.times(10000) ?: 0) (it.child?.episode ?: 0) + (it.child?.season?.times(10000) ?: 0)
} // episode sorting by episode, lowest to highest } // episode sorting by episode, lowest to highest
} }
try {
val stat = StatFs(Environment.getExternalStorageDirectory().path)
val stat = StatFs(Environment.getExternalStorageDirectory().path) val localBytesAvailable = stat.availableBytes//stat.blockSizeLong * stat.blockCountLong
val localTotalBytes = stat.blockSizeLong * stat.blockCountLong
val localDownloadedBytes = visual.sumOf { it.totalBytes }
val localBytesAvailable = stat.availableBytes//stat.blockSizeLong * stat.blockCountLong _usedBytes.postValue(localTotalBytes - localBytesAvailable - localDownloadedBytes)
val localTotalBytes = stat.blockSizeLong * stat.blockCountLong _availableBytes.postValue(localBytesAvailable)
val localDownloadedBytes = visual.sumOf { it.totalBytes } _downloadBytes.postValue(localDownloadedBytes)
} catch (e : Exception) {
_usedBytes.postValue(localTotalBytes - localBytesAvailable - localDownloadedBytes) _downloadBytes.postValue(0)
_availableBytes.postValue(localBytesAvailable) logError(e)
_downloadBytes.postValue(localDownloadedBytes) }
_headerCards.postValue(visual) _headerCards.postValue(visual)
} }

View file

@ -20,8 +20,13 @@ class EasyDownloadButton : IDisposable {
val id: Int val id: Int
} }
private var _clickCallback: ((DownloadClickEvent) -> Unit)? = null
private var _imageChangeCallback: ((Pair<Int, String>) -> Unit)? = null
override fun dispose() { override fun dispose() {
try { try {
_clickCallback = null
_imageChangeCallback = null
downloadProgressEventListener?.let { VideoDownloadManager.downloadProgressEvent -= it } downloadProgressEventListener?.let { VideoDownloadManager.downloadProgressEvent -= it }
downloadStatusEventListener?.let { VideoDownloadManager.downloadStatusEvent -= it } downloadStatusEventListener?.let { VideoDownloadManager.downloadStatusEvent -= it }
} catch (e: Exception) { } catch (e: Exception) {
@ -119,6 +124,8 @@ class EasyDownloadButton : IDisposable {
clickCallback: (DownloadClickEvent) -> Unit, clickCallback: (DownloadClickEvent) -> Unit,
isTextPercentage: Boolean = false isTextPercentage: Boolean = false
) { ) {
_clickCallback = clickCallback
_imageChangeCallback = downloadImageChangeCallback
var lastState: VideoDownloadManager.DownloadType? = null var lastState: VideoDownloadManager.DownloadType? = null
var currentBytes = setupCurrentBytes ?: 0 var currentBytes = setupCurrentBytes ?: 0
var totalBytes = setupTotalBytes ?: 0 var totalBytes = setupTotalBytes ?: 0
@ -142,7 +149,7 @@ class EasyDownloadButton : IDisposable {
} else { } else {
Pair(R.drawable.netflix_download, R.string.download) Pair(R.drawable.netflix_download, R.string.download)
} }
downloadImageChangeCallback.invoke( _imageChangeCallback?.invoke(
Pair( Pair(
img.first, img.first,
downloadView.context.getString(img.second) downloadView.context.getString(img.second)
@ -223,7 +230,7 @@ class EasyDownloadButton : IDisposable {
downloadView.setOnClickListener { downloadView.setOnClickListener {
if (currentBytes <= 0) { if (currentBytes <= 0) {
clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_DOWNLOAD, data)) _clickCallback?.invoke(DownloadClickEvent(DOWNLOAD_ACTION_DOWNLOAD, data))
} else { } else {
val list = arrayListOf( val list = arrayListOf(
Pair(DOWNLOAD_ACTION_PLAY_FILE, R.string.popup_play_file), Pair(DOWNLOAD_ACTION_PLAY_FILE, R.string.popup_play_file),
@ -243,7 +250,7 @@ class EasyDownloadButton : IDisposable {
it.popupMenuNoIcons( it.popupMenuNoIcons(
list list
) { ) {
clickCallback.invoke(DownloadClickEvent(itemId, data)) _clickCallback?.invoke(DownloadClickEvent(itemId, data))
} }
} }
} }

View file

@ -350,6 +350,7 @@ abstract class AbstractPlayerFragment(
resizeMode = getKey(RESIZE_MODE_KEY) ?: 0 resizeMode = getKey(RESIZE_MODE_KEY) ?: 0
resize(resizeMode, false) resize(resizeMode, false)
player.releaseCallbacks()
player.initCallbacks( player.initCallbacks(
playerUpdated = ::playerUpdated, playerUpdated = ::playerUpdated,
updateIsPlaying = ::updateIsPlaying, updateIsPlaying = ::updateIsPlaying,

View file

@ -108,6 +108,21 @@ class CS3IPlayer : IPlayer {
private var playerUpdated: ((Any?) -> Unit)? = null private var playerUpdated: ((Any?) -> Unit)? = null
private var embeddedSubtitlesFetched: ((List<SubtitleData>) -> Unit)? = null private var embeddedSubtitlesFetched: ((List<SubtitleData>) -> Unit)? = null
override fun releaseCallbacks() {
playerUpdated = null
updateIsPlaying = null
requestAutoFocus = null
playerError = null
playerDimensionsLoaded = null
requestedListeningPercentages = null
playerPositionChanged = null
nextEpisode = null
prevEpisode = null
subtitlesUpdates = null
embeddedSubtitlesFetched = null
requestSubtitleUpdate = null
}
override fun initCallbacks( override fun initCallbacks(
playerUpdated: (Any?) -> Unit, playerUpdated: (Any?) -> Unit,
updateIsPlaying: ((Pair<CSPlayerLoading, CSPlayerLoading>) -> Unit)?, updateIsPlaying: ((Pair<CSPlayerLoading, CSPlayerLoading>) -> Unit)?,

View file

@ -315,6 +315,8 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
override fun onDestroy() { override fun onDestroy() {
exitFullscreen() exitFullscreen()
player.release()
player.releaseCallbacks()
super.onDestroy() super.onDestroy()
} }
@ -1104,7 +1106,6 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
// init variables // init variables
setPlayBackSpeed(getKey(PLAYBACK_SPEED_KEY) ?: 1.0f) setPlayBackSpeed(getKey(PLAYBACK_SPEED_KEY) ?: 1.0f)

View file

@ -359,12 +359,12 @@ class GeneratorPlayer : FullScreenPlayer() {
} }
}) })
dialog.search_filter.setOnClickListener { dialog.search_filter.setOnClickListener { view ->
val lang639_1 = languages.map { it.ISO_639_1 } val lang639_1 = languages.map { it.ISO_639_1 }
activity?.showDialog( activity?.showDialog(
languages.map { it.languageName }, languages.map { it.languageName },
lang639_1.indexOf(currentLanguageTwoLetters), lang639_1.indexOf(currentLanguageTwoLetters),
context.getString(R.string.subs_subtitle_languages), view?.context?.getString(R.string.subs_subtitle_languages) ?: return@setOnClickListener,
true, true,
{ } { }
) { index -> ) { index ->
@ -609,7 +609,7 @@ class GeneratorPlayer : FullScreenPlayer() {
val currentPrefMedia = val currentPrefMedia =
settingsManager.getString( settingsManager.getString(
getString(R.string.subtitles_encoding_key), ctx.getString(R.string.subtitles_encoding_key),
null null
) )

View file

@ -88,6 +88,7 @@ interface IPlayer {
subtitlesUpdates: (() -> Unit)? = null, // callback from player to inform that subtitles have updated in some way subtitlesUpdates: (() -> Unit)? = null, // callback from player to inform that subtitles have updated in some way
embeddedSubtitlesFetched: ((List<SubtitleData>) -> Unit)? = null, // callback from player to give all embedded subtitles embeddedSubtitlesFetched: ((List<SubtitleData>) -> Unit)? = null, // callback from player to give all embedded subtitles
) )
fun releaseCallbacks()
fun updateSubtitleStyle(style: SaveCaptionStyle) fun updateSubtitleStyle(style: SaveCaptionStyle)
fun saveData() fun saveData()

View file

@ -129,10 +129,14 @@ object UIHelper {
} }
fun Activity?.navigate(@IdRes navigation: Int, arguments: Bundle? = null) { fun Activity?.navigate(@IdRes navigation: Int, arguments: Bundle? = null) {
if (this is FragmentActivity) { try {
(supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as? NavHostFragment?)?.navController?.navigate( if (this is FragmentActivity) {
navigation, arguments (supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as? NavHostFragment?)?.navController?.navigate(
) navigation, arguments
)
}
} catch (e : Exception) {
logError(e)
} }
} }

View file

@ -20,6 +20,7 @@
--> -->
<LinearLayout <LinearLayout
android:id="@+id/download_storage_appbar" android:id="@+id/download_storage_appbar"
tools:visibility="visible"
android:visibility="gone" android:visibility="gone"
android:layout_margin="10dp" android:layout_margin="10dp"
android:orientation="vertical" android:orientation="vertical"

View file

@ -360,14 +360,15 @@
tools:text="121min" /> tools:text="121min" />
</com.lagradost.cloudstream3.widget.FlowLayout> </com.lagradost.cloudstream3.widget.FlowLayout>
<!-- <!--
This has half margin and half padding to make TV focus on description look better. This has half margin and half padding to make TV focus on description look better.
The focus outline now settles between the poster and text. The focus outline now settles between the poster and text.
--> -->
<FrameLayout <FrameLayout
android:layout_marginHorizontal="5dp" android:layout_marginHorizontal="5dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<TextView <TextView
android:padding="5dp" android:padding="5dp"
android:maxLength="1000" android:maxLength="1000"
@ -848,9 +849,10 @@ The focus outline now settles between the poster and text.
android:textColor="?attr/grayTextColor" android:textColor="?attr/grayTextColor"
android:textSize="17sp" android:textSize="17sp"
android:textStyle="normal" android:textStyle="normal"
android:text="Episode 1022 will be released in" /> tools:text="Episode 1022 will be released in" />
<TextView <TextView
android:paddingEnd="5dp"
android:paddingStart="5dp" android:paddingStart="5dp"
android:gravity="center" android:gravity="center"
android:id="@+id/result_next_airing_time" android:id="@+id/result_next_airing_time"
@ -903,6 +905,7 @@ The focus outline now settles between the poster and text.
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="0dp" android:layout_marginTop="0dp"
android:clipToPadding="false" android:clipToPadding="false"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:descendantFocusability="afterDescendants" android:descendantFocusability="afterDescendants"
android:paddingBottom="100dp" android:paddingBottom="100dp"
tools:listitem="@layout/result_episode" /> tools:listitem="@layout/result_episode" />