mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
downloads playable
This commit is contained in:
parent
3bf76a9563
commit
5ffb53bf1c
11 changed files with 405 additions and 175 deletions
|
@ -1,25 +1,29 @@
|
|||
package com.lagradost.cloudstream3
|
||||
|
||||
import android.R.attr
|
||||
import android.app.PictureInPictureParams
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.ColorStateList
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.navigation.NavOptions
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.navigation.ui.AppBarConfiguration
|
||||
import androidx.navigation.ui.setupWithNavController
|
||||
import com.google.android.gms.cast.framework.CastButtonFactory
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
import com.lagradost.cloudstream3.UIHelper.checkWrite
|
||||
import com.lagradost.cloudstream3.UIHelper.getResourceColor
|
||||
import com.lagradost.cloudstream3.UIHelper.hasPIPPermission
|
||||
import com.lagradost.cloudstream3.UIHelper.isUsingMobileData
|
||||
import com.lagradost.cloudstream3.UIHelper.requestRW
|
||||
import com.lagradost.cloudstream3.UIHelper.shouldShowPIPMode
|
||||
import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver
|
||||
import com.lagradost.cloudstream3.ui.download.DownloadChildFragment
|
||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||
import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
||||
import com.lagradost.cloudstream3.utils.DataStore.removeKey
|
||||
|
@ -54,6 +58,7 @@ class MainActivity : AppCompatActivity() {
|
|||
var canShowPipMode: Boolean = false
|
||||
var isInPIPMode: Boolean = false
|
||||
lateinit var mainContext: MainActivity
|
||||
lateinit var navOptions: NavOptions
|
||||
|
||||
//https://github.com/anggrayudi/SimpleStorage/blob/4eb6306efb6cdfae4e34f170c8b9d4e135b04d51/sample/src/main/java/com/anggrayudi/storage/sample/activity/MainActivity.kt#L624
|
||||
const val REQUEST_CODE_STORAGE_ACCESS = 1
|
||||
|
@ -89,6 +94,17 @@ class MainActivity : AppCompatActivity() {
|
|||
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 (currentFragment != null && supportFragmentManager.fragments.size > 2) {
|
||||
//MainActivity.showNavbar()
|
||||
supportFragmentManager.beginTransaction()
|
||||
|
@ -146,15 +162,35 @@ class MainActivity : AppCompatActivity() {
|
|||
hasPIPPermission() // CHECK IF FEATURE IS ENABLED IN SETTINGS
|
||||
|
||||
val navController = findNavController(R.id.nav_host_fragment)
|
||||
// Passing each menu ID as a set of Ids because each
|
||||
// menu should be considered as top level destinations.
|
||||
val appBarConfiguration = AppBarConfiguration(
|
||||
setOf(
|
||||
R.id.navigation_home, R.id.navigation_search, R.id.navigation_notifications
|
||||
)
|
||||
)
|
||||
//setupActionBarWithNavController(navController, appBarConfiguration)
|
||||
navView.setupWithNavController(navController)
|
||||
|
||||
navOptions = NavOptions.Builder()
|
||||
.setLaunchSingleTop(true)
|
||||
.setEnterAnim(R.anim.nav_enter_anim)
|
||||
.setExitAnim(R.anim.nav_exit_anim)
|
||||
.setPopEnterAnim(R.anim.nav_pop_enter)
|
||||
.setPopExitAnim(R.anim.nav_pop_exit)
|
||||
.setPopUpTo(navController.graph.startDestination, false)
|
||||
.build()
|
||||
|
||||
navView.setOnNavigationItemSelectedListener { item ->
|
||||
when (item.itemId) {
|
||||
// R.id.navigation_home -> {
|
||||
// navController.navigate(R.id.navigation_home, null, navOptions)
|
||||
//}
|
||||
R.id.navigation_search -> {
|
||||
navController.navigate(R.id.navigation_search, null, navOptions)
|
||||
}
|
||||
R.id.navigation_downloads -> {
|
||||
navController.navigate(R.id.navigation_downloads, null, navOptions)
|
||||
}
|
||||
R.id.navigation_settings -> {
|
||||
navController.navigate(R.id.navigation_settings, null, navOptions)
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
navView.itemRippleColor = ColorStateList.valueOf(getResourceColor(R.attr.colorPrimary, 0.1f))
|
||||
|
||||
if (!checkWrite()) {
|
||||
requestRW()
|
||||
|
|
|
@ -19,6 +19,7 @@ import android.view.MenuItem
|
|||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import androidx.annotation.AttrRes
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.view.ContextThemeWrapper
|
||||
|
@ -26,6 +27,10 @@ import androidx.appcompat.view.menu.MenuBuilder
|
|||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.alpha
|
||||
import androidx.core.graphics.blue
|
||||
import androidx.core.graphics.green
|
||||
import androidx.core.graphics.red
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.google.android.gms.cast.framework.CastContext
|
||||
|
@ -59,6 +64,20 @@ object UIHelper {
|
|||
1337)
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
fun Context.getResourceColor(@AttrRes resource: Int, alphaFactor: Float = 1f): Int {
|
||||
val typedArray = obtainStyledAttributes(intArrayOf(resource))
|
||||
val color = typedArray.getColor(0, 0)
|
||||
typedArray.recycle()
|
||||
|
||||
if (alphaFactor < 1f) {
|
||||
val alpha = (color.alpha * alphaFactor).roundToInt()
|
||||
return Color.argb(alpha, color.red, color.green, color.blue)
|
||||
}
|
||||
|
||||
return color
|
||||
}
|
||||
|
||||
fun AppCompatActivity.loadResult(url: String, slug: String, apiName: String) {
|
||||
this.runOnUiThread {
|
||||
viewModelStore.clear()
|
||||
|
|
|
@ -4,14 +4,20 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
||||
import com.lagradost.cloudstream3.ui.player.PlayerData
|
||||
import com.lagradost.cloudstream3.ui.player.PlayerFragment
|
||||
import com.lagradost.cloudstream3.ui.player.UriData
|
||||
import com.lagradost.cloudstream3.ui.result.getRealPosition
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||
import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||
import kotlinx.android.synthetic.main.fragment_child_downloads.*
|
||||
|
@ -68,6 +74,11 @@ class DownloadChildFragment : Fragment() {
|
|||
}
|
||||
context?.fixPaddingStatusbar(download_child_root)
|
||||
|
||||
download_child_toolbar.title = name
|
||||
download_child_toolbar.setNavigationIcon(R.drawable.ic_baseline_arrow_back_24)
|
||||
download_child_toolbar.setNavigationOnClickListener {
|
||||
activity?.onBackPressed()
|
||||
}
|
||||
|
||||
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> =
|
||||
DownloadChildAdapter(
|
||||
|
@ -77,6 +88,28 @@ class DownloadChildFragment : Fragment() {
|
|||
val info =
|
||||
VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(requireContext(), click.data.id)
|
||||
?: return@DownloadChildAdapter
|
||||
|
||||
(requireActivity() as AppCompatActivity).supportFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(
|
||||
R.anim.enter_anim,
|
||||
R.anim.exit_anim,
|
||||
R.anim.pop_enter,
|
||||
R.anim.pop_exit
|
||||
)
|
||||
.add(
|
||||
R.id.homeRoot,
|
||||
PlayerFragment.newInstance(
|
||||
UriData(
|
||||
info.path.toString(),
|
||||
click.data.id,
|
||||
name ?: "null",
|
||||
click.data.episode,
|
||||
click.data.season
|
||||
),
|
||||
context?.getViewPos(click.data.id)?.position ?: 0
|
||||
)
|
||||
)
|
||||
.commit()
|
||||
}
|
||||
}
|
||||
download_child_list.adapter = adapter
|
||||
|
|
|
@ -8,8 +8,10 @@ import android.view.ViewGroup
|
|||
import android.widget.LinearLayout
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.lagradost.cloudstream3.MainActivity
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
||||
import com.lagradost.cloudstream3.isMovieType
|
||||
|
@ -64,6 +66,7 @@ class DownloadFragment : Fragment() {
|
|||
observe(downloadsViewModel.downloadBytes) {
|
||||
download_app_txt?.text = "App • ${getBytesAsText(it)}GB"
|
||||
download_app?.setLayoutWidth(it)
|
||||
download_storage_appbar?.visibility = View.VISIBLE
|
||||
}
|
||||
return inflater.inflate(R.layout.fragment_downloads, container, false)
|
||||
}
|
||||
|
@ -79,10 +82,11 @@ class DownloadFragment : Fragment() {
|
|||
}
|
||||
else {
|
||||
val folder = getFolderName(DOWNLOAD_EPISODE_CACHE, click.data.id.toString())
|
||||
activity?.supportFragmentManager?.beginTransaction()
|
||||
?.setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim, R.anim.pop_enter, R.anim.pop_exit)
|
||||
?.add(R.id.homeRoot, DownloadChildFragment.newInstance(click.data.name, folder))
|
||||
?.commit()
|
||||
val navController = activity?.findNavController(R.id.nav_host_fragment)
|
||||
navController?.navigate(R.id.navigation_download_child, Bundle().apply {
|
||||
putString("folder", folder)
|
||||
putString("name", click.data.name)
|
||||
})
|
||||
}
|
||||
}
|
||||
download_list.adapter = adapter
|
||||
|
|
|
@ -39,6 +39,7 @@ import androidx.transition.TransitionManager
|
|||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper
|
||||
import com.fasterxml.jackson.module.kotlin.KotlinModule
|
||||
import com.fasterxml.jackson.module.kotlin.readValue
|
||||
import com.google.android.exoplayer2.*
|
||||
import com.google.android.exoplayer2.C.TIME_UNSET
|
||||
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory
|
||||
|
@ -71,6 +72,7 @@ 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.ResultViewModel
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.getVideoContentUri
|
||||
import com.lagradost.cloudstream3.utils.CastHelper.startCast
|
||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
||||
|
@ -81,7 +83,6 @@ import com.lagradost.cloudstream3.utils.getId
|
|||
import kotlinx.android.synthetic.main.fragment_player.*
|
||||
import kotlinx.android.synthetic.main.player_custom_layout.*
|
||||
import kotlinx.coroutines.*
|
||||
import java.io.File
|
||||
import javax.net.ssl.HttpsURLConnection
|
||||
import javax.net.ssl.SSLContext
|
||||
import javax.net.ssl.SSLSession
|
||||
|
@ -131,6 +132,14 @@ data class PlayerData(
|
|||
val mirrorId: Int,
|
||||
)
|
||||
|
||||
data class UriData(
|
||||
val uri: String,
|
||||
val id: Int?,
|
||||
val name: String,
|
||||
val episode: Int?,
|
||||
val season: Int?,
|
||||
)
|
||||
|
||||
// YE, I KNOW, THIS COULD BE HANDLED A LOT BETTER
|
||||
class PlayerFragment : Fragment() {
|
||||
private var isCurrentlyPlaying: Boolean = false
|
||||
|
@ -143,6 +152,9 @@ class PlayerFragment : Fragment() {
|
|||
private var isPlayerPlaying = true
|
||||
private lateinit var viewModel: ResultViewModel
|
||||
private lateinit var playerData: PlayerData
|
||||
private lateinit var uriData: UriData
|
||||
private var isDownloadedFile = false
|
||||
private var downloadId = 0
|
||||
private var isLoading = true
|
||||
private var isShowing = true
|
||||
private lateinit var exoPlayer: SimpleExoPlayer
|
||||
|
@ -598,14 +610,31 @@ class PlayerFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun newInstance(uriData: UriData, startPos: Long? = null) =
|
||||
PlayerFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
//println(data)
|
||||
putString("uriData", mapper.writeValueAsString(uriData))
|
||||
|
||||
if (startPos != null) {
|
||||
putLong(STATE_RESUME_POSITION, startPos)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun savePos() {
|
||||
if (this::exoPlayer.isInitialized) {
|
||||
if (exoPlayer.duration > 0 && exoPlayer.currentPosition > 0) {
|
||||
context?.let { ctx ->
|
||||
ctx.setViewPos(getEpisode()?.id, exoPlayer.currentPosition, exoPlayer.duration)
|
||||
viewModel.reloadEpisodes(ctx)
|
||||
ctx.setViewPos(
|
||||
if (isDownloadedFile) uriData.id else getEpisode()?.id,
|
||||
exoPlayer.currentPosition,
|
||||
exoPlayer.duration
|
||||
)
|
||||
if (!isDownloadedFile)
|
||||
viewModel.reloadEpisodes(ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -774,7 +803,7 @@ class PlayerFragment : Fragment() {
|
|||
navigationBarHeight = requireContext().getNavigationBarHeight()
|
||||
statusBarHeight = requireContext().getStatusBarHeight()
|
||||
|
||||
if (activity?.isCastApiAvailable() == true) {
|
||||
if (activity?.isCastApiAvailable() == true && !isDownloadedFile) {
|
||||
CastButtonFactory.setUpMediaRouteButton(activity, player_media_route_button)
|
||||
val castContext = CastContext.getSharedInstance(requireContext())
|
||||
|
||||
|
@ -852,14 +881,24 @@ class PlayerFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
isDownloadedFile = false
|
||||
arguments?.getString("uriData")?.let {
|
||||
uriData = mapper.readValue(it)
|
||||
isDownloadedFile = true
|
||||
}
|
||||
|
||||
arguments?.getString("data")?.let {
|
||||
playerData = mapper.readValue(it, PlayerData::class.java)
|
||||
playerData = mapper.readValue(it)
|
||||
}
|
||||
|
||||
arguments?.getLong(STATE_RESUME_POSITION)?.let {
|
||||
playbackPosition = it
|
||||
}
|
||||
|
||||
sources_btt.visibility =
|
||||
if (isDownloadedFile) View.GONE else View.VISIBLE
|
||||
player_media_route_button.visibility =
|
||||
if (isDownloadedFile) View.GONE else View.VISIBLE
|
||||
if (savedInstanceState != null) {
|
||||
currentWindow = savedInstanceState.getInt(STATE_RESUME_WINDOW)
|
||||
playbackPosition = savedInstanceState.getLong(STATE_RESUME_POSITION)
|
||||
|
@ -883,60 +922,61 @@ class PlayerFragment : Fragment() {
|
|||
android.provider.Settings.System.CONTENT_URI, true, volumeObserver
|
||||
)
|
||||
|
||||
viewModel = ViewModelProvider(requireActivity()).get(ResultViewModel::class.java)
|
||||
if (!isDownloadedFile) {
|
||||
viewModel = ViewModelProvider(requireActivity()).get(ResultViewModel::class.java)
|
||||
|
||||
observeDirectly(viewModel.episodes) { _episodes ->
|
||||
episodes = _episodes
|
||||
if (isLoading) {
|
||||
if (playerData.episodeIndex > 0 && playerData.episodeIndex < episodes.size) {
|
||||
observeDirectly(viewModel.episodes) { _episodes ->
|
||||
episodes = _episodes
|
||||
if (isLoading) {
|
||||
if (playerData.episodeIndex > 0 && playerData.episodeIndex < episodes.size) {
|
||||
|
||||
} else {
|
||||
// WHAT THE FUCK DID YOU DO
|
||||
} else {
|
||||
// WHAT THE FUCK DID YOU DO
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
observe(viewModel.apiName) {
|
||||
apiName = it
|
||||
}
|
||||
observe(viewModel.apiName) {
|
||||
apiName = it
|
||||
}
|
||||
|
||||
overlay_loading_skip_button?.alpha = 0.5f
|
||||
observeDirectly(viewModel.allEpisodes) { _allEpisodes ->
|
||||
allEpisodes = _allEpisodes
|
||||
overlay_loading_skip_button?.alpha = 0.5f
|
||||
observeDirectly(viewModel.allEpisodes) { _allEpisodes ->
|
||||
allEpisodes = _allEpisodes
|
||||
|
||||
val current = getUrls()
|
||||
if (current != null) {
|
||||
if (current.isNotEmpty()) {
|
||||
overlay_loading_skip_button?.alpha = 1f
|
||||
val current = getUrls()
|
||||
if (current != null) {
|
||||
if (current.isNotEmpty()) {
|
||||
overlay_loading_skip_button?.alpha = 1f
|
||||
} else {
|
||||
overlay_loading_skip_button?.alpha = 0.5f
|
||||
}
|
||||
} else {
|
||||
overlay_loading_skip_button?.alpha = 0.5f
|
||||
}
|
||||
} else {
|
||||
overlay_loading_skip_button?.alpha = 0.5f
|
||||
}
|
||||
}
|
||||
|
||||
observeDirectly(viewModel.allEpisodesSubs) { _allEpisodesSubs ->
|
||||
allEpisodesSubs = _allEpisodesSubs
|
||||
}
|
||||
observeDirectly(viewModel.allEpisodesSubs) { _allEpisodesSubs ->
|
||||
allEpisodesSubs = _allEpisodesSubs
|
||||
}
|
||||
|
||||
observeDirectly(viewModel.resultResponse) { data ->
|
||||
when (data) {
|
||||
is Resource.Success -> {
|
||||
val d = data.value
|
||||
if (d is LoadResponse) {
|
||||
localData = d
|
||||
currentPoster = d.posterUrl
|
||||
currentHeaderName = d.name
|
||||
currentIsMovie = !d.isEpisodeBased()
|
||||
observeDirectly(viewModel.resultResponse) { data ->
|
||||
when (data) {
|
||||
is Resource.Success -> {
|
||||
val d = data.value
|
||||
if (d is LoadResponse) {
|
||||
localData = d
|
||||
currentPoster = d.posterUrl
|
||||
currentHeaderName = d.name
|
||||
currentIsMovie = !d.isEpisodeBased()
|
||||
}
|
||||
}
|
||||
is Resource.Failure -> {
|
||||
//WTF, HOW DID YOU EVEN GET HERE
|
||||
}
|
||||
}
|
||||
is Resource.Failure -> {
|
||||
//WTF, HOW DID YOU EVEN GET HERE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val fastForwardTime = settingsManager.getInt("fast_forward_button_time", 10)
|
||||
exo_rew_text.text = fastForwardTime.toString()
|
||||
exo_ffwd_text.text = fastForwardTime.toString()
|
||||
|
@ -1193,7 +1233,7 @@ class PlayerFragment : Fragment() {
|
|||
}
|
||||
|
||||
private fun hasNextEpisode(): Boolean {
|
||||
return episodes.size > playerData.episodeIndex + 1
|
||||
return !isDownloadedFile && episodes.size > playerData.episodeIndex + 1 // TODO FIX DOWNLOADS NEXT EPISODE
|
||||
}
|
||||
|
||||
private var isCurrentlySkippingEp = false
|
||||
|
@ -1335,8 +1375,8 @@ class PlayerFragment : Fragment() {
|
|||
private val updateProgressAction = Runnable { updateProgressBar() }*/
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
fun initPlayer(currentUrl: ExtractorLink?) {
|
||||
if (currentUrl == null) return
|
||||
fun initPlayer(currentUrl: ExtractorLink?, uri: String? = null) {
|
||||
if (currentUrl == null && uri == null) return
|
||||
isCurrentlyPlaying = true
|
||||
hasUsedFirstRender = false
|
||||
|
||||
|
@ -1347,9 +1387,9 @@ class PlayerFragment : Fragment() {
|
|||
exoPlayer.release()
|
||||
}
|
||||
val isOnline =
|
||||
currentUrl.url.startsWith("https://") || currentUrl.url.startsWith("http://")
|
||||
currentUrl != null && (currentUrl.url.startsWith("https://") || currentUrl.url.startsWith("http://"))
|
||||
|
||||
if (settingsManager.getBoolean("ignore_ssl", true)) {
|
||||
if (settingsManager.getBoolean("ignore_ssl", true) && !isDownloadedFile) {
|
||||
// Disables ssl check
|
||||
val sslContext: SSLContext = SSLContext.getInstance("TLS")
|
||||
sslContext.init(null, arrayOf(SSLTrustManager()), java.security.SecureRandom())
|
||||
|
@ -1367,7 +1407,8 @@ class PlayerFragment : Fragment() {
|
|||
/*FastAniApi.currentHeaders?.forEach {
|
||||
dataSource.setRequestProperty(it.key, it.value)
|
||||
}*/
|
||||
dataSource.setRequestProperty("Referer", currentUrl.referer)
|
||||
if (currentUrl != null)
|
||||
dataSource.setRequestProperty("Referer", currentUrl.referer)
|
||||
dataSource
|
||||
} else {
|
||||
DefaultDataSourceFactory(requireContext(), USER_AGENT).createDataSource()
|
||||
|
@ -1375,15 +1416,31 @@ class PlayerFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
val mimeType = if (currentUrl.isM3u8) MimeTypes.APPLICATION_M3U8 else MimeTypes.APPLICATION_MP4
|
||||
val mimeType =
|
||||
if (currentUrl == null && uri != null)
|
||||
MimeTypes.APPLICATION_MP4 else
|
||||
if (currentUrl?.isM3u8 == true)
|
||||
MimeTypes.APPLICATION_M3U8
|
||||
else
|
||||
MimeTypes.APPLICATION_MP4
|
||||
|
||||
val mediaItemBuilder = MediaItem.Builder()
|
||||
//Replace needed for android 6.0.0 https://github.com/google/ExoPlayer/issues/5983
|
||||
.setMimeType(mimeType)
|
||||
|
||||
if (isOnline) {
|
||||
if (currentUrl != null) {
|
||||
mediaItemBuilder.setUri(currentUrl.url)
|
||||
} else {
|
||||
mediaItemBuilder.setUri(Uri.fromFile(File(currentUrl.url)))
|
||||
} else if (uri != null) {
|
||||
val uriPrimary = Uri.parse(uri)
|
||||
if (uriPrimary.scheme == "content") {
|
||||
mediaItemBuilder.setUri(uriPrimary)
|
||||
// video_title?.text = uriPrimary.toString()
|
||||
} else {
|
||||
//mediaItemBuilder.setUri(Uri.parse(currentUrl.url))
|
||||
val realUri = getVideoContentUri(requireContext(), uri)
|
||||
// video_title?.text = uri.toString()
|
||||
mediaItemBuilder.setUri(realUri)
|
||||
}
|
||||
}
|
||||
|
||||
val mediaItem = mediaItemBuilder.build()
|
||||
|
@ -1401,7 +1458,7 @@ class PlayerFragment : Fragment() {
|
|||
.setTrackSelector(trackSelector)
|
||||
|
||||
_exoPlayer.setMediaSourceFactory(DefaultMediaSourceFactory(CustomFactory()))
|
||||
println("START POS: " + playbackPosition)
|
||||
|
||||
exoPlayer = _exoPlayer.build().apply {
|
||||
playWhenReady = isPlayerPlaying
|
||||
seekTo(currentWindow, playbackPosition)
|
||||
|
@ -1431,24 +1488,38 @@ class PlayerFragment : Fragment() {
|
|||
exoPlayer.playbackParameters = PlaybackParameters(playbackSpeed)
|
||||
player_speed_text?.text = "Speed (${playbackSpeed}x)".replace(".0x", "x")
|
||||
|
||||
if (localData != null) {
|
||||
var hName: String? = null
|
||||
var epEpisode: Int? = null
|
||||
var epSeason: Int? = null
|
||||
var isEpisodeBased = true
|
||||
|
||||
if (isDownloadedFile) {
|
||||
hName = uriData.name
|
||||
epEpisode = uriData.episode
|
||||
epSeason = uriData.season
|
||||
isEpisodeBased = epEpisode != null
|
||||
video_title_rez?.text = ""
|
||||
} else if (localData != null && currentUrl != null) {
|
||||
val data = localData!!
|
||||
val localEpisode = getEpisode()
|
||||
if (localEpisode != null) {
|
||||
val episode = localEpisode.episode
|
||||
val season: Int? = localEpisode.season
|
||||
val isEpisodeBased = data.isEpisodeBased()
|
||||
video_title?.text = data.name +
|
||||
if (isEpisodeBased)
|
||||
if (season == null)
|
||||
" - Episode $episode"
|
||||
else
|
||||
" \"S${season}:E${episode}\""
|
||||
else ""
|
||||
epEpisode = localEpisode.episode
|
||||
epSeason = localEpisode.season
|
||||
hName = data.name
|
||||
isEpisodeBased = data.isEpisodeBased()
|
||||
video_title_rez?.text = currentUrl.name
|
||||
}
|
||||
}
|
||||
|
||||
//TODO FIX
|
||||
video_title?.text = hName +
|
||||
if (isEpisodeBased)
|
||||
if (epSeason == null)
|
||||
" - Episode $epEpisode"
|
||||
else
|
||||
" \"S${epSeason}:E${epEpisode}\""
|
||||
else ""
|
||||
|
||||
/*
|
||||
exo_remaining.text = Util.getStringForTime(formatBuilder,
|
||||
formatter,
|
||||
|
@ -1465,8 +1536,10 @@ class PlayerFragment : Fragment() {
|
|||
|
||||
val height = exoPlayer.videoFormat?.height
|
||||
val width = exoPlayer.videoFormat?.width
|
||||
|
||||
video_title_rez?.text =
|
||||
if (height == null || width == null) currentUrl.name else "${currentUrl.name} - ${width}x${height}"
|
||||
if (height == null || width == null) currentUrl?.name
|
||||
?: "" else if (isDownloadedFile) "${width}x${height}" else "${currentUrl?.name} - ${width}x${height}"
|
||||
|
||||
if (!hasUsedFirstRender) { // DON'T WANT TO SET MULTIPLE MESSAGES
|
||||
changeSkip()
|
||||
|
@ -1521,11 +1594,11 @@ class PlayerFragment : Fragment() {
|
|||
}
|
||||
|
||||
override fun onPlayerError(error: ExoPlaybackException) {
|
||||
println("CURRENT URL: " + currentUrl.url)
|
||||
println("CURRENT URL: " + currentUrl?.url ?: uri)
|
||||
// Lets pray this doesn't spam Toasts :)
|
||||
when (error.type) {
|
||||
ExoPlaybackException.TYPE_SOURCE -> {
|
||||
if (currentUrl.url != "") {
|
||||
if (currentUrl?.url != "") {
|
||||
Toast.makeText(
|
||||
activity,
|
||||
"Source error\n" + error.sourceException.message,
|
||||
|
@ -1565,6 +1638,9 @@ class PlayerFragment : Fragment() {
|
|||
//http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun initPlayer() {
|
||||
if (isDownloadedFile) {
|
||||
initPlayer(null, uriData.uri)
|
||||
}
|
||||
println("INIT PLAYER")
|
||||
view?.setOnTouchListener { _, _ -> return@setOnTouchListener true } // VERY IMPORTANT https://stackoverflow.com/questions/28818926/prevent-clicking-on-a-button-in-an-activity-while-showing-a-fragment
|
||||
val tempCurrentUrls = getUrls()
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package com.lagradost.cloudstream3.utils
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.provider.MediaStore
|
||||
|
||||
object AppUtils {
|
||||
fun getVideoContentUri(context: Context, videoFilePath: String): Uri? {
|
||||
val cursor = context.contentResolver.query(
|
||||
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, arrayOf(MediaStore.Video.Media._ID),
|
||||
MediaStore.Video.Media.DATA + "=? ", arrayOf(videoFilePath), null
|
||||
)
|
||||
return if (cursor != null && cursor.moveToFirst()) {
|
||||
val id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID))
|
||||
cursor.close()
|
||||
Uri.withAppendedPath(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "" + id)
|
||||
} else {
|
||||
val values = ContentValues()
|
||||
values.put(MediaStore.Video.Media.DATA, videoFilePath)
|
||||
context.contentResolver.insert(
|
||||
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
android:background="@color/bitDarkerGrayBackground"
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:background="?attr/darkBackground"
|
||||
android:id="@+id/download_child_root"
|
||||
android:orientation="vertical"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
@ -9,11 +9,29 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.download.DownloadFragment">
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:background="@android:color/transparent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/download_child_toolbar"
|
||||
android:paddingTop="@dimen/navbarHeight"
|
||||
tools:title="Overlord"
|
||||
android:background="?attr/darkBackground"
|
||||
app:navigationIconTint="?attr/iconColor"
|
||||
app:titleTextColor="?attr/textColor"
|
||||
app:layout_scrollFlags="scroll|enterAlways"
|
||||
android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
</com.google.android.material.appbar.MaterialToolbar>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:layout_margin="10dp"
|
||||
android:background="?attr/bitDarkerGrayBackground"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
android:padding="10dp"
|
||||
tools:listitem="@layout/download_child_episode"
|
||||
android:id="@+id/download_child_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="match_parent">
|
||||
</androidx.recyclerview.widget.RecyclerView>
|
||||
</LinearLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/download_root"
|
||||
android:orientation="vertical"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
@ -7,100 +7,114 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/darkBackground"
|
||||
tools:context=".ui.download.DownloadFragment">
|
||||
<LinearLayout
|
||||
android:layout_margin="10dp"
|
||||
android:orientation="vertical"
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:background="?attr/darkBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:layout_marginBottom="5dp"
|
||||
android:text="@string/download_storage_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
</TextView>
|
||||
<!--
|
||||
For Scroll add to LinearLayout
|
||||
app:layout_scrollFlags="scroll|enterAlways"
|
||||
-->
|
||||
<LinearLayout
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="12dp"
|
||||
android:orientation="horizontal">
|
||||
<View
|
||||
android:layout_weight="0.5"
|
||||
android:id="@+id/download_used"
|
||||
android:background="@color/usedStorageColor"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"/>
|
||||
<View
|
||||
android:id="@+id/download_app"
|
||||
android:layout_weight="0.10"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"/>
|
||||
<View
|
||||
android:id="@+id/download_free"
|
||||
android:layout_weight="0.10"
|
||||
android:background="@color/freeStorageColor"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:id="@+id/download_storage_appbar"
|
||||
android:visibility="gone"
|
||||
android:layout_margin="10dp"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<View
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_marginTop="5dp"
|
||||
<TextView
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="@color/usedStorageColor"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"/>
|
||||
<TextView
|
||||
android:id="@+id/download_used_txt"
|
||||
android:layout_gravity="center_vertical"
|
||||
tools:text="Used • 30.58GB"
|
||||
android:textSize="12sp"
|
||||
android:textColor="?attr/textColor"
|
||||
android:text="@string/download_storage_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
android:layout_height="wrap_content">
|
||||
</TextView>
|
||||
<LinearLayout
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="12dp"
|
||||
android:orientation="horizontal">
|
||||
<View
|
||||
android:layout_weight="0.5"
|
||||
android:id="@+id/download_used"
|
||||
android:background="@color/usedStorageColor"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"/>
|
||||
<View
|
||||
android:id="@+id/download_app"
|
||||
android:layout_weight="0.10"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"/>
|
||||
<View
|
||||
android:id="@+id/download_free"
|
||||
android:layout_weight="0.10"
|
||||
android:background="@color/freeStorageColor"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<View
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="@color/usedStorageColor"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"/>
|
||||
<TextView
|
||||
android:id="@+id/download_used_txt"
|
||||
android:layout_gravity="center_vertical"
|
||||
tools:text="Used • 30.58GB"
|
||||
android:textSize="12sp"
|
||||
android:textColor="?attr/textColor"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<View
|
||||
android:layout_margin="5dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"/>
|
||||
<TextView
|
||||
android:id="@+id/download_app_txt"
|
||||
android:layout_gravity="center_vertical"
|
||||
tools:text="App • 30.58GB"
|
||||
android:textSize="12sp"
|
||||
android:textColor="?attr/textColor"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
<View
|
||||
android:layout_margin="5dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="@color/freeStorageColor"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"/>
|
||||
<TextView
|
||||
android:id="@+id/download_free_txt"
|
||||
android:textSize="12sp"
|
||||
android:layout_gravity="center_vertical"
|
||||
tools:text="Free • 30.58GB"
|
||||
android:textColor="?attr/textColor"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
<View
|
||||
android:layout_margin="5dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"/>
|
||||
<TextView
|
||||
android:id="@+id/download_app_txt"
|
||||
android:layout_gravity="center_vertical"
|
||||
tools:text="App • 30.58GB"
|
||||
android:textSize="12sp"
|
||||
android:textColor="?attr/textColor"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
<View
|
||||
android:layout_margin="5dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="@color/freeStorageColor"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"/>
|
||||
<TextView
|
||||
android:id="@+id/download_free_txt"
|
||||
android:textSize="12sp"
|
||||
android:layout_gravity="center_vertical"
|
||||
tools:text="Free • 30.58GB"
|
||||
android:textColor="?attr/textColor"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:layout_margin="10dp"
|
||||
android:background="?attr/bitDarkerGrayBackground"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
android:padding="10dp"
|
||||
android:id="@+id/download_list"
|
||||
android:layout_width="match_parent"
|
||||
tools:listitem="@layout/download_header_episode"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="match_parent">
|
||||
</androidx.recyclerview.widget.RecyclerView>
|
||||
<TextView
|
||||
android:id="@+id/text_no_downloads"
|
||||
|
@ -115,4 +129,4 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
</LinearLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -8,9 +8,7 @@
|
|||
android:id="@+id/searchRoot"
|
||||
tools:context=".ui.search.SearchFragment"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="@dimen/navbarHeight"
|
||||
|
||||
android:background="@color/grayBackground">
|
||||
android:layout_marginTop="@dimen/navbarHeight">
|
||||
<FrameLayout android:visibility="visible"
|
||||
android:layout_margin="10dp"
|
||||
android:background="@drawable/search_background"
|
||||
|
|
|
@ -1,23 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!--
|
||||
<item
|
||||
android:id="@+id/navigation_home"
|
||||
android:icon="@drawable/ic_home_black_24dp"
|
||||
android:title="@string/title_home"/>
|
||||
|
||||
-->
|
||||
<item
|
||||
android:id="@+id/navigation_search"
|
||||
android:icon="@drawable/search_icon"
|
||||
android:title="@string/title_search"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/navigation_notifications"
|
||||
android:id="@+id/navigation_downloads"
|
||||
android:icon="@drawable/netflix_download"
|
||||
android:title="@string/title_downloads"/>
|
||||
<item
|
||||
android:id="@+id/navigation_settings"
|
||||
android:icon="@drawable/ic_outline_settings_24"
|
||||
android:title="@string/title_settings"/>
|
||||
|
||||
</menu>
|
|
@ -18,7 +18,7 @@
|
|||
tools:layout="@layout/fragment_search"/>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/navigation_notifications"
|
||||
android:id="@+id/navigation_downloads"
|
||||
android:name="com.lagradost.cloudstream3.ui.download.DownloadFragment"
|
||||
android:label="@string/title_downloads"
|
||||
tools:layout="@layout/fragment_downloads"/>
|
||||
|
@ -28,4 +28,11 @@
|
|||
android:name="com.lagradost.cloudstream3.ui.settings.SettingsFragment"
|
||||
android:label="@string/title_settings"
|
||||
/>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/navigation_download_child"
|
||||
android:layout_height="match_parent"
|
||||
android:name="com.lagradost.cloudstream3.ui.download.DownloadChildFragment"
|
||||
android:label="@string/title_settings"
|
||||
/>
|
||||
</navigation>
|
Loading…
Reference in a new issue