forked from recloudstream/cloudstream
		
	play any stream & a bit of work on invideoplayer episodes & no links found last error
This commit is contained in:
		
							parent
							
								
									bb7400638a
								
							
						
					
					
						commit
						e7e63b4855
					
				
					 17 changed files with 585 additions and 528 deletions
				
			
		|  | @ -36,7 +36,7 @@ android { | |||
|         targetSdkVersion 30 | ||||
| 
 | ||||
|         versionCode 48 | ||||
|         versionName "2.10.30" | ||||
|         versionName "2.10.31" | ||||
| 
 | ||||
|         resValue "string", "app_version", | ||||
|                 "${defaultConfig.versionName}${versionNameSuffix ?: ""}" | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ import com.lagradost.cloudstream3.utils.loadExtractor | |||
| import org.jsoup.Jsoup | ||||
| 
 | ||||
| class HDMovie5 : MainAPI() { | ||||
|     override var mainUrl = "https://hdmovie2.org" | ||||
|     override var mainUrl = "https://Hdmovie2.biz" | ||||
|     override var name = "HDMovie" | ||||
|     override var lang = "hi" | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,8 +2,11 @@ package com.lagradost.cloudstream3.movieproviders | |||
| 
 | ||||
| import android.util.Log | ||||
| import com.fasterxml.jackson.annotation.JsonProperty | ||||
| import com.lagradost.cloudstream3.* | ||||
| 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.TmdbProvider | ||||
| import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.extractRabbitStream | ||||
|  | @ -15,7 +18,7 @@ import com.lagradost.cloudstream3.utils.loadExtractor | |||
| class TwoEmbedProvider : TmdbProvider() { | ||||
|     override val apiName = "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 instantLinkLoading = false | ||||
|     override val supportedTypes = setOf( | ||||
|  |  | |||
|  | @ -12,21 +12,40 @@ import com.lagradost.cloudstream3.R | |||
| import com.lagradost.cloudstream3.utils.UIHelper.adjustAlpha | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.toPx | ||||
| import java.lang.ref.WeakReference | ||||
| 
 | ||||
| 
 | ||||
| class MyMiniControllerFragment : MiniControllerFragment() { | ||||
|     var currentColor: Int = 0 | ||||
| 
 | ||||
|     // I KNOW, KINDA SPAGHETTI SOLUTION, BUT IT WORKS | ||||
|     override fun onInflate(context: Context, attributeSet: AttributeSet, bundle: Bundle?) { | ||||
|         val obtainStyledAttributes = context.obtainStyledAttributes(attributeSet, R.styleable.CustomCast, 0, 0) | ||||
|         if (obtainStyledAttributes.hasValue(R.styleable.CustomCast_customCastBackgroundColor)) { | ||||
|             currentColor = obtainStyledAttributes.getColor(R.styleable.CustomCast_customCastBackgroundColor, 0) | ||||
|         } | ||||
|         obtainStyledAttributes.recycle() | ||||
|         super.onInflate(context, attributeSet, bundle) | ||||
|     override fun onDestroy() { | ||||
|         currentColor = 0 | ||||
|         super.onDestroy() | ||||
|     } | ||||
| 
 | ||||
|     // 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?) { | ||||
|         super.onViewCreated(view, savedInstanceState) | ||||
|  | @ -38,18 +57,24 @@ class MyMiniControllerFragment : MiniControllerFragment() { | |||
|             val containerCurrent: RelativeLayout? = view.findViewById(R.id.container_current) | ||||
| 
 | ||||
|             context?.let { ctx -> | ||||
|                 progressBar?.setBackgroundColor(adjustAlpha(ctx.colorFromAttribute(R.attr.colorPrimary), 0.35f)) | ||||
|                 val params = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, 2.toPx) | ||||
|                 progressBar?.setBackgroundColor( | ||||
|                     adjustAlpha( | ||||
|                         ctx.colorFromAttribute(R.attr.colorPrimary), | ||||
|                         0.35f | ||||
|                     ) | ||||
|                 ) | ||||
|                 val params = RelativeLayout.LayoutParams( | ||||
|                     RelativeLayout.LayoutParams.MATCH_PARENT, | ||||
|                     2.toPx | ||||
|                 ) | ||||
| 
 | ||||
|                 progressBar?.layoutParams = params | ||||
| 
 | ||||
|                 if (currentColor != 0) { | ||||
|                     containerCurrent?.setBackgroundColor(currentColor) | ||||
|                 } | ||||
|                 val color = currentColor | ||||
|                 if (color != 0) | ||||
|                     containerCurrent?.setBackgroundColor(color) | ||||
|             } | ||||
|             val child = containerAll?.getChildAt(0) | ||||
|             child?.alpha = 0f // REMOVE GRADIENT | ||||
| 
 | ||||
|         } catch (e: Exception) { | ||||
|             // JUST IN CASE | ||||
|         } | ||||
|  |  | |||
|  | @ -31,12 +31,8 @@ class DownloadChildFragment : Fragment() { | |||
| 
 | ||||
|     override fun onDestroyView() { | ||||
|         (download_child_list?.adapter as DownloadChildAdapter?)?.killAdapter() | ||||
|         super.onDestroyView() | ||||
|     } | ||||
| 
 | ||||
|     override fun onDestroy() { | ||||
|         downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent -= it } | ||||
|         super.onDestroy() | ||||
|         super.onDestroyView() | ||||
|     } | ||||
| 
 | ||||
|     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { | ||||
|  |  | |||
|  | @ -65,16 +65,12 @@ class DownloadFragment : Fragment() { | |||
|     } | ||||
| 
 | ||||
|     override fun onDestroyView() { | ||||
|         (download_list?.adapter as DownloadHeaderAdapter?)?.killAdapter() | ||||
|         super.onDestroyView() | ||||
|     } | ||||
| 
 | ||||
|     override fun onDestroy() { | ||||
|         if (downloadDeleteEventListener != null) { | ||||
|             VideoDownloadManager.downloadDeleteEvent -= downloadDeleteEventListener!! | ||||
|             downloadDeleteEventListener = null | ||||
|         } | ||||
|         super.onDestroy() | ||||
|         (download_list?.adapter as DownloadHeaderAdapter?)?.killAdapter() | ||||
|         super.onDestroyView() | ||||
|     } | ||||
| 
 | ||||
|     override fun onCreateView( | ||||
|  | @ -83,7 +79,17 @@ class DownloadFragment : Fragment() { | |||
|         savedInstanceState: Bundle? | ||||
|     ): View? { | ||||
|         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) { | ||||
|             text_no_downloads.text = it | ||||
|         } | ||||
|  | @ -114,16 +120,8 @@ class DownloadFragment : Fragment() { | |||
|                     getBytesAsText(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> = | ||||
|             DownloadHeaderAdapter( | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ import androidx.lifecycle.MutableLiveData | |||
| import androidx.lifecycle.ViewModel | ||||
| import androidx.lifecycle.viewModelScope | ||||
| 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_HEADER_CACHE | ||||
| import com.lagradost.cloudstream3.utils.DataStore.getFolderName | ||||
|  | @ -100,16 +101,20 @@ class DownloadViewModel : ViewModel() { | |||
|                 (it.child?.episode ?: 0) + (it.child?.season?.times(10000) ?: 0) | ||||
|             } // 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 | ||||
|         val localTotalBytes = stat.blockSizeLong * stat.blockCountLong | ||||
|         val localDownloadedBytes = visual.sumOf { it.totalBytes } | ||||
| 
 | ||||
|         _usedBytes.postValue(localTotalBytes - localBytesAvailable - localDownloadedBytes) | ||||
|         _availableBytes.postValue(localBytesAvailable) | ||||
|         _downloadBytes.postValue(localDownloadedBytes) | ||||
|             _usedBytes.postValue(localTotalBytes - localBytesAvailable - localDownloadedBytes) | ||||
|             _availableBytes.postValue(localBytesAvailable) | ||||
|             _downloadBytes.postValue(localDownloadedBytes) | ||||
|         } catch (e : Exception) { | ||||
|             _downloadBytes.postValue(0) | ||||
|             logError(e) | ||||
|         } | ||||
| 
 | ||||
|         _headerCards.postValue(visual) | ||||
|     } | ||||
|  |  | |||
|  | @ -20,8 +20,13 @@ class EasyDownloadButton : IDisposable { | |||
|         val id: Int | ||||
|     } | ||||
| 
 | ||||
|     private var _clickCallback: ((DownloadClickEvent) -> Unit)? = null | ||||
|     private var _imageChangeCallback: ((Pair<Int, String>) -> Unit)? = null | ||||
| 
 | ||||
|     override fun dispose() { | ||||
|         try { | ||||
|             _clickCallback = null | ||||
|             _imageChangeCallback = null | ||||
|             downloadProgressEventListener?.let { VideoDownloadManager.downloadProgressEvent -= it } | ||||
|             downloadStatusEventListener?.let { VideoDownloadManager.downloadStatusEvent -= it } | ||||
|         } catch (e: Exception) { | ||||
|  | @ -119,6 +124,8 @@ class EasyDownloadButton : IDisposable { | |||
|         clickCallback: (DownloadClickEvent) -> Unit, | ||||
|         isTextPercentage: Boolean = false | ||||
|     ) { | ||||
|         _clickCallback = clickCallback | ||||
|         _imageChangeCallback = downloadImageChangeCallback | ||||
|         var lastState: VideoDownloadManager.DownloadType? = null | ||||
|         var currentBytes = setupCurrentBytes ?: 0 | ||||
|         var totalBytes = setupTotalBytes ?: 0 | ||||
|  | @ -142,7 +149,7 @@ class EasyDownloadButton : IDisposable { | |||
|             } else { | ||||
|                 Pair(R.drawable.netflix_download, R.string.download) | ||||
|             } | ||||
|             downloadImageChangeCallback.invoke( | ||||
|             _imageChangeCallback?.invoke( | ||||
|                 Pair( | ||||
|                     img.first, | ||||
|                     downloadView.context.getString(img.second) | ||||
|  | @ -223,7 +230,7 @@ class EasyDownloadButton : IDisposable { | |||
| 
 | ||||
|         downloadView.setOnClickListener { | ||||
|             if (currentBytes <= 0) { | ||||
|                 clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_DOWNLOAD, data)) | ||||
|                 _clickCallback?.invoke(DownloadClickEvent(DOWNLOAD_ACTION_DOWNLOAD, data)) | ||||
|             } else { | ||||
|                 val list = arrayListOf( | ||||
|                     Pair(DOWNLOAD_ACTION_PLAY_FILE, R.string.popup_play_file), | ||||
|  | @ -243,7 +250,7 @@ class EasyDownloadButton : IDisposable { | |||
|                 it.popupMenuNoIcons( | ||||
|                     list | ||||
|                 ) { | ||||
|                     clickCallback.invoke(DownloadClickEvent(itemId, data)) | ||||
|                     _clickCallback?.invoke(DownloadClickEvent(itemId, data)) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  |  | |||
|  | @ -350,6 +350,7 @@ abstract class AbstractPlayerFragment( | |||
|         resizeMode = getKey(RESIZE_MODE_KEY) ?: 0 | ||||
|         resize(resizeMode, false) | ||||
| 
 | ||||
|         player.releaseCallbacks() | ||||
|         player.initCallbacks( | ||||
|             playerUpdated = ::playerUpdated, | ||||
|             updateIsPlaying = ::updateIsPlaying, | ||||
|  |  | |||
|  | @ -108,6 +108,21 @@ class CS3IPlayer : IPlayer { | |||
|     private var playerUpdated: ((Any?) -> 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( | ||||
|         playerUpdated: (Any?) -> Unit, | ||||
|         updateIsPlaying: ((Pair<CSPlayerLoading, CSPlayerLoading>) -> Unit)?, | ||||
|  |  | |||
|  | @ -315,6 +315,8 @@ open class FullScreenPlayer : AbstractPlayerFragment() { | |||
| 
 | ||||
|     override fun onDestroy() { | ||||
|         exitFullscreen() | ||||
|         player.release() | ||||
|         player.releaseCallbacks() | ||||
|         super.onDestroy() | ||||
|     } | ||||
| 
 | ||||
|  | @ -1104,7 +1106,6 @@ open class FullScreenPlayer : AbstractPlayerFragment() { | |||
|     @SuppressLint("ClickableViewAccessibility") | ||||
|     override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||||
|         super.onViewCreated(view, savedInstanceState) | ||||
| 
 | ||||
|         // init variables | ||||
|         setPlayBackSpeed(getKey(PLAYBACK_SPEED_KEY) ?: 1.0f) | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 } | ||||
|             activity?.showDialog( | ||||
|                 languages.map { it.languageName }, | ||||
|                 lang639_1.indexOf(currentLanguageTwoLetters), | ||||
|                 context.getString(R.string.subs_subtitle_languages), | ||||
|                 view?.context?.getString(R.string.subs_subtitle_languages) ?: return@setOnClickListener, | ||||
|                 true, | ||||
|                 { } | ||||
|             ) { index -> | ||||
|  | @ -609,7 +609,7 @@ class GeneratorPlayer : FullScreenPlayer() { | |||
| 
 | ||||
|                     val currentPrefMedia = | ||||
|                         settingsManager.getString( | ||||
|                             getString(R.string.subtitles_encoding_key), | ||||
|                             ctx.getString(R.string.subtitles_encoding_key), | ||||
|                             null | ||||
|                         ) | ||||
| 
 | ||||
|  |  | |||
|  | @ -88,6 +88,7 @@ interface IPlayer { | |||
|         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 | ||||
|     ) | ||||
|     fun releaseCallbacks() | ||||
| 
 | ||||
|     fun updateSubtitleStyle(style: SaveCaptionStyle) | ||||
|     fun saveData() | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -129,10 +129,14 @@ object UIHelper { | |||
|     } | ||||
| 
 | ||||
|     fun Activity?.navigate(@IdRes navigation: Int, arguments: Bundle? = null) { | ||||
|         if (this is FragmentActivity) { | ||||
|             (supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as? NavHostFragment?)?.navController?.navigate( | ||||
|                 navigation, arguments | ||||
|             ) | ||||
|         try { | ||||
|             if (this is FragmentActivity) { | ||||
|                 (supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as? NavHostFragment?)?.navController?.navigate( | ||||
|                     navigation, arguments | ||||
|                 ) | ||||
|             } | ||||
|         } catch (e : Exception) { | ||||
|             logError(e) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -20,6 +20,7 @@ | |||
|         --> | ||||
|         <LinearLayout | ||||
|                 android:id="@+id/download_storage_appbar" | ||||
|                 tools:visibility="visible" | ||||
|                 android:visibility="gone" | ||||
|                 android:layout_margin="10dp" | ||||
|                 android:orientation="vertical" | ||||
|  |  | |||
|  | @ -360,14 +360,15 @@ | |||
|                                         tools:text="121min" /> | ||||
|                             </com.lagradost.cloudstream3.widget.FlowLayout> | ||||
| 
 | ||||
| <!-- | ||||
| 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. | ||||
| --> | ||||
|                             <!-- | ||||
|                             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. | ||||
|                             --> | ||||
|                             <FrameLayout | ||||
|                                     android:layout_marginHorizontal="5dp" | ||||
|                                     android:layout_width="match_parent" | ||||
|                                     android:layout_height="match_parent"> | ||||
| 
 | ||||
|                                 <TextView | ||||
|                                         android:padding="5dp" | ||||
|                                         android:maxLength="1000" | ||||
|  | @ -848,9 +849,10 @@ The focus outline now settles between the poster and text. | |||
|                                         android:textColor="?attr/grayTextColor" | ||||
|                                         android:textSize="17sp" | ||||
|                                         android:textStyle="normal" | ||||
|                                         android:text="Episode 1022 will be released in" /> | ||||
|                                         tools:text="Episode 1022 will be released in" /> | ||||
| 
 | ||||
|                                 <TextView | ||||
|                                         android:paddingEnd="5dp" | ||||
|                                         android:paddingStart="5dp" | ||||
|                                         android:gravity="center" | ||||
|                                         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_marginTop="0dp" | ||||
|                                     android:clipToPadding="false" | ||||
|                                     app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" | ||||
|                                     android:descendantFocusability="afterDescendants" | ||||
|                                     android:paddingBottom="100dp" | ||||
|                                     tools:listitem="@layout/result_episode" /> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue