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
|
package com.lagradost.cloudstream3
|
||||||
|
|
||||||
import android.R.attr
|
|
||||||
import android.app.PictureInPictureParams
|
import android.app.PictureInPictureParams
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.res.ColorStateList
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.navigation.NavOptions
|
||||||
import androidx.navigation.findNavController
|
import androidx.navigation.findNavController
|
||||||
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
import androidx.navigation.ui.AppBarConfiguration
|
import androidx.navigation.ui.AppBarConfiguration
|
||||||
import androidx.navigation.ui.setupWithNavController
|
import androidx.navigation.ui.setupWithNavController
|
||||||
import com.google.android.gms.cast.framework.CastButtonFactory
|
import com.google.android.gms.cast.framework.CastButtonFactory
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
import com.lagradost.cloudstream3.UIHelper.checkWrite
|
import com.lagradost.cloudstream3.UIHelper.checkWrite
|
||||||
|
import com.lagradost.cloudstream3.UIHelper.getResourceColor
|
||||||
import com.lagradost.cloudstream3.UIHelper.hasPIPPermission
|
import com.lagradost.cloudstream3.UIHelper.hasPIPPermission
|
||||||
import com.lagradost.cloudstream3.UIHelper.isUsingMobileData
|
import com.lagradost.cloudstream3.UIHelper.isUsingMobileData
|
||||||
import com.lagradost.cloudstream3.UIHelper.requestRW
|
import com.lagradost.cloudstream3.UIHelper.requestRW
|
||||||
import com.lagradost.cloudstream3.UIHelper.shouldShowPIPMode
|
import com.lagradost.cloudstream3.UIHelper.shouldShowPIPMode
|
||||||
import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver
|
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.getKey
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.removeKey
|
import com.lagradost.cloudstream3.utils.DataStore.removeKey
|
||||||
|
@ -54,6 +58,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
var canShowPipMode: Boolean = false
|
var canShowPipMode: Boolean = false
|
||||||
var isInPIPMode: Boolean = false
|
var isInPIPMode: Boolean = false
|
||||||
lateinit var mainContext: MainActivity
|
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
|
//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
|
const val REQUEST_CODE_STORAGE_ACCESS = 1
|
||||||
|
@ -89,6 +94,17 @@ class MainActivity : AppCompatActivity() {
|
||||||
it.isVisible
|
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) {
|
if (currentFragment != null && supportFragmentManager.fragments.size > 2) {
|
||||||
//MainActivity.showNavbar()
|
//MainActivity.showNavbar()
|
||||||
supportFragmentManager.beginTransaction()
|
supportFragmentManager.beginTransaction()
|
||||||
|
@ -146,15 +162,35 @@ class MainActivity : AppCompatActivity() {
|
||||||
hasPIPPermission() // CHECK IF FEATURE IS ENABLED IN SETTINGS
|
hasPIPPermission() // CHECK IF FEATURE IS ENABLED IN SETTINGS
|
||||||
|
|
||||||
val navController = findNavController(R.id.nav_host_fragment)
|
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.
|
navOptions = NavOptions.Builder()
|
||||||
val appBarConfiguration = AppBarConfiguration(
|
.setLaunchSingleTop(true)
|
||||||
setOf(
|
.setEnterAnim(R.anim.nav_enter_anim)
|
||||||
R.id.navigation_home, R.id.navigation_search, R.id.navigation_notifications
|
.setExitAnim(R.anim.nav_exit_anim)
|
||||||
)
|
.setPopEnterAnim(R.anim.nav_pop_enter)
|
||||||
)
|
.setPopExitAnim(R.anim.nav_pop_exit)
|
||||||
//setupActionBarWithNavController(navController, appBarConfiguration)
|
.setPopUpTo(navController.graph.startDestination, false)
|
||||||
navView.setupWithNavController(navController)
|
.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()) {
|
if (!checkWrite()) {
|
||||||
requestRW()
|
requestRW()
|
||||||
|
|
|
@ -19,6 +19,7 @@ import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
|
import androidx.annotation.AttrRes
|
||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.view.ContextThemeWrapper
|
import androidx.appcompat.view.ContextThemeWrapper
|
||||||
|
@ -26,6 +27,10 @@ import androidx.appcompat.view.menu.MenuBuilder
|
||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.content.ContextCompat
|
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.fragment.app.FragmentActivity
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.google.android.gms.cast.framework.CastContext
|
import com.google.android.gms.cast.framework.CastContext
|
||||||
|
@ -59,6 +64,20 @@ object UIHelper {
|
||||||
1337)
|
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) {
|
fun AppCompatActivity.loadResult(url: String, slug: String, apiName: String) {
|
||||||
this.runOnUiThread {
|
this.runOnUiThread {
|
||||||
viewModelStore.clear()
|
viewModelStore.clear()
|
||||||
|
|
|
@ -4,14 +4,20 @@ import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
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.Coroutines.main
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
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.VideoDownloadHelper
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||||
import kotlinx.android.synthetic.main.fragment_child_downloads.*
|
import kotlinx.android.synthetic.main.fragment_child_downloads.*
|
||||||
|
@ -68,6 +74,11 @@ class DownloadChildFragment : Fragment() {
|
||||||
}
|
}
|
||||||
context?.fixPaddingStatusbar(download_child_root)
|
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> =
|
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> =
|
||||||
DownloadChildAdapter(
|
DownloadChildAdapter(
|
||||||
|
@ -77,6 +88,28 @@ class DownloadChildFragment : Fragment() {
|
||||||
val info =
|
val info =
|
||||||
VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(requireContext(), click.data.id)
|
VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(requireContext(), click.data.id)
|
||||||
?: return@DownloadChildAdapter
|
?: 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
|
download_child_list.adapter = adapter
|
||||||
|
|
|
@ -8,8 +8,10 @@ import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.navigation.findNavController
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.lagradost.cloudstream3.MainActivity
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
||||||
import com.lagradost.cloudstream3.isMovieType
|
import com.lagradost.cloudstream3.isMovieType
|
||||||
|
@ -64,6 +66,7 @@ class DownloadFragment : Fragment() {
|
||||||
observe(downloadsViewModel.downloadBytes) {
|
observe(downloadsViewModel.downloadBytes) {
|
||||||
download_app_txt?.text = "App • ${getBytesAsText(it)}GB"
|
download_app_txt?.text = "App • ${getBytesAsText(it)}GB"
|
||||||
download_app?.setLayoutWidth(it)
|
download_app?.setLayoutWidth(it)
|
||||||
|
download_storage_appbar?.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
return inflater.inflate(R.layout.fragment_downloads, container, false)
|
return inflater.inflate(R.layout.fragment_downloads, container, false)
|
||||||
}
|
}
|
||||||
|
@ -79,10 +82,11 @@ class DownloadFragment : Fragment() {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val folder = getFolderName(DOWNLOAD_EPISODE_CACHE, click.data.id.toString())
|
val folder = getFolderName(DOWNLOAD_EPISODE_CACHE, click.data.id.toString())
|
||||||
activity?.supportFragmentManager?.beginTransaction()
|
val navController = activity?.findNavController(R.id.nav_host_fragment)
|
||||||
?.setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim, R.anim.pop_enter, R.anim.pop_exit)
|
navController?.navigate(R.id.navigation_download_child, Bundle().apply {
|
||||||
?.add(R.id.homeRoot, DownloadChildFragment.newInstance(click.data.name, folder))
|
putString("folder", folder)
|
||||||
?.commit()
|
putString("name", click.data.name)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
download_list.adapter = adapter
|
download_list.adapter = adapter
|
||||||
|
|
|
@ -39,6 +39,7 @@ import androidx.transition.TransitionManager
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||||
import com.fasterxml.jackson.databind.json.JsonMapper
|
import com.fasterxml.jackson.databind.json.JsonMapper
|
||||||
import com.fasterxml.jackson.module.kotlin.KotlinModule
|
import com.fasterxml.jackson.module.kotlin.KotlinModule
|
||||||
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import com.google.android.exoplayer2.*
|
import com.google.android.exoplayer2.*
|
||||||
import com.google.android.exoplayer2.C.TIME_UNSET
|
import com.google.android.exoplayer2.C.TIME_UNSET
|
||||||
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory
|
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.mvvm.observeDirectly
|
||||||
import com.lagradost.cloudstream3.ui.result.ResultEpisode
|
import com.lagradost.cloudstream3.ui.result.ResultEpisode
|
||||||
import com.lagradost.cloudstream3.ui.result.ResultViewModel
|
import com.lagradost.cloudstream3.ui.result.ResultViewModel
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.getVideoContentUri
|
||||||
import com.lagradost.cloudstream3.utils.CastHelper.startCast
|
import com.lagradost.cloudstream3.utils.CastHelper.startCast
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
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.fragment_player.*
|
||||||
import kotlinx.android.synthetic.main.player_custom_layout.*
|
import kotlinx.android.synthetic.main.player_custom_layout.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import java.io.File
|
|
||||||
import javax.net.ssl.HttpsURLConnection
|
import javax.net.ssl.HttpsURLConnection
|
||||||
import javax.net.ssl.SSLContext
|
import javax.net.ssl.SSLContext
|
||||||
import javax.net.ssl.SSLSession
|
import javax.net.ssl.SSLSession
|
||||||
|
@ -131,6 +132,14 @@ data class PlayerData(
|
||||||
val mirrorId: Int,
|
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
|
// YE, I KNOW, THIS COULD BE HANDLED A LOT BETTER
|
||||||
class PlayerFragment : Fragment() {
|
class PlayerFragment : Fragment() {
|
||||||
private var isCurrentlyPlaying: Boolean = false
|
private var isCurrentlyPlaying: Boolean = false
|
||||||
|
@ -143,6 +152,9 @@ class PlayerFragment : Fragment() {
|
||||||
private var isPlayerPlaying = true
|
private var isPlayerPlaying = true
|
||||||
private lateinit var viewModel: ResultViewModel
|
private lateinit var viewModel: ResultViewModel
|
||||||
private lateinit var playerData: PlayerData
|
private lateinit var playerData: PlayerData
|
||||||
|
private lateinit var uriData: UriData
|
||||||
|
private var isDownloadedFile = false
|
||||||
|
private var downloadId = 0
|
||||||
private var isLoading = true
|
private var isLoading = true
|
||||||
private var isShowing = true
|
private var isShowing = true
|
||||||
private lateinit var exoPlayer: SimpleExoPlayer
|
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() {
|
private fun savePos() {
|
||||||
if (this::exoPlayer.isInitialized) {
|
if (this::exoPlayer.isInitialized) {
|
||||||
if (exoPlayer.duration > 0 && exoPlayer.currentPosition > 0) {
|
if (exoPlayer.duration > 0 && exoPlayer.currentPosition > 0) {
|
||||||
context?.let { ctx ->
|
context?.let { ctx ->
|
||||||
ctx.setViewPos(getEpisode()?.id, exoPlayer.currentPosition, exoPlayer.duration)
|
ctx.setViewPos(
|
||||||
viewModel.reloadEpisodes(ctx)
|
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()
|
navigationBarHeight = requireContext().getNavigationBarHeight()
|
||||||
statusBarHeight = requireContext().getStatusBarHeight()
|
statusBarHeight = requireContext().getStatusBarHeight()
|
||||||
|
|
||||||
if (activity?.isCastApiAvailable() == true) {
|
if (activity?.isCastApiAvailable() == true && !isDownloadedFile) {
|
||||||
CastButtonFactory.setUpMediaRouteButton(activity, player_media_route_button)
|
CastButtonFactory.setUpMediaRouteButton(activity, player_media_route_button)
|
||||||
val castContext = CastContext.getSharedInstance(requireContext())
|
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 {
|
arguments?.getString("data")?.let {
|
||||||
playerData = mapper.readValue(it, PlayerData::class.java)
|
playerData = mapper.readValue(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
arguments?.getLong(STATE_RESUME_POSITION)?.let {
|
arguments?.getLong(STATE_RESUME_POSITION)?.let {
|
||||||
playbackPosition = it
|
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) {
|
if (savedInstanceState != null) {
|
||||||
currentWindow = savedInstanceState.getInt(STATE_RESUME_WINDOW)
|
currentWindow = savedInstanceState.getInt(STATE_RESUME_WINDOW)
|
||||||
playbackPosition = savedInstanceState.getLong(STATE_RESUME_POSITION)
|
playbackPosition = savedInstanceState.getLong(STATE_RESUME_POSITION)
|
||||||
|
@ -883,60 +922,61 @@ class PlayerFragment : Fragment() {
|
||||||
android.provider.Settings.System.CONTENT_URI, true, volumeObserver
|
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 ->
|
observeDirectly(viewModel.episodes) { _episodes ->
|
||||||
episodes = _episodes
|
episodes = _episodes
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
if (playerData.episodeIndex > 0 && playerData.episodeIndex < episodes.size) {
|
if (playerData.episodeIndex > 0 && playerData.episodeIndex < episodes.size) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// WHAT THE FUCK DID YOU DO
|
// WHAT THE FUCK DID YOU DO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
observe(viewModel.apiName) {
|
observe(viewModel.apiName) {
|
||||||
apiName = it
|
apiName = it
|
||||||
}
|
}
|
||||||
|
|
||||||
overlay_loading_skip_button?.alpha = 0.5f
|
overlay_loading_skip_button?.alpha = 0.5f
|
||||||
observeDirectly(viewModel.allEpisodes) { _allEpisodes ->
|
observeDirectly(viewModel.allEpisodes) { _allEpisodes ->
|
||||||
allEpisodes = _allEpisodes
|
allEpisodes = _allEpisodes
|
||||||
|
|
||||||
val current = getUrls()
|
val current = getUrls()
|
||||||
if (current != null) {
|
if (current != null) {
|
||||||
if (current.isNotEmpty()) {
|
if (current.isNotEmpty()) {
|
||||||
overlay_loading_skip_button?.alpha = 1f
|
overlay_loading_skip_button?.alpha = 1f
|
||||||
|
} else {
|
||||||
|
overlay_loading_skip_button?.alpha = 0.5f
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
overlay_loading_skip_button?.alpha = 0.5f
|
overlay_loading_skip_button?.alpha = 0.5f
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
overlay_loading_skip_button?.alpha = 0.5f
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
observeDirectly(viewModel.allEpisodesSubs) { _allEpisodesSubs ->
|
observeDirectly(viewModel.allEpisodesSubs) { _allEpisodesSubs ->
|
||||||
allEpisodesSubs = _allEpisodesSubs
|
allEpisodesSubs = _allEpisodesSubs
|
||||||
}
|
}
|
||||||
|
|
||||||
observeDirectly(viewModel.resultResponse) { data ->
|
observeDirectly(viewModel.resultResponse) { data ->
|
||||||
when (data) {
|
when (data) {
|
||||||
is Resource.Success -> {
|
is Resource.Success -> {
|
||||||
val d = data.value
|
val d = data.value
|
||||||
if (d is LoadResponse) {
|
if (d is LoadResponse) {
|
||||||
localData = d
|
localData = d
|
||||||
currentPoster = d.posterUrl
|
currentPoster = d.posterUrl
|
||||||
currentHeaderName = d.name
|
currentHeaderName = d.name
|
||||||
currentIsMovie = !d.isEpisodeBased()
|
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)
|
val fastForwardTime = settingsManager.getInt("fast_forward_button_time", 10)
|
||||||
exo_rew_text.text = fastForwardTime.toString()
|
exo_rew_text.text = fastForwardTime.toString()
|
||||||
exo_ffwd_text.text = fastForwardTime.toString()
|
exo_ffwd_text.text = fastForwardTime.toString()
|
||||||
|
@ -1193,7 +1233,7 @@ class PlayerFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hasNextEpisode(): Boolean {
|
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
|
private var isCurrentlySkippingEp = false
|
||||||
|
@ -1335,8 +1375,8 @@ class PlayerFragment : Fragment() {
|
||||||
private val updateProgressAction = Runnable { updateProgressBar() }*/
|
private val updateProgressAction = Runnable { updateProgressBar() }*/
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
fun initPlayer(currentUrl: ExtractorLink?) {
|
fun initPlayer(currentUrl: ExtractorLink?, uri: String? = null) {
|
||||||
if (currentUrl == null) return
|
if (currentUrl == null && uri == null) return
|
||||||
isCurrentlyPlaying = true
|
isCurrentlyPlaying = true
|
||||||
hasUsedFirstRender = false
|
hasUsedFirstRender = false
|
||||||
|
|
||||||
|
@ -1347,9 +1387,9 @@ class PlayerFragment : Fragment() {
|
||||||
exoPlayer.release()
|
exoPlayer.release()
|
||||||
}
|
}
|
||||||
val isOnline =
|
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
|
// Disables ssl check
|
||||||
val sslContext: SSLContext = SSLContext.getInstance("TLS")
|
val sslContext: SSLContext = SSLContext.getInstance("TLS")
|
||||||
sslContext.init(null, arrayOf(SSLTrustManager()), java.security.SecureRandom())
|
sslContext.init(null, arrayOf(SSLTrustManager()), java.security.SecureRandom())
|
||||||
|
@ -1367,7 +1407,8 @@ class PlayerFragment : Fragment() {
|
||||||
/*FastAniApi.currentHeaders?.forEach {
|
/*FastAniApi.currentHeaders?.forEach {
|
||||||
dataSource.setRequestProperty(it.key, it.value)
|
dataSource.setRequestProperty(it.key, it.value)
|
||||||
}*/
|
}*/
|
||||||
dataSource.setRequestProperty("Referer", currentUrl.referer)
|
if (currentUrl != null)
|
||||||
|
dataSource.setRequestProperty("Referer", currentUrl.referer)
|
||||||
dataSource
|
dataSource
|
||||||
} else {
|
} else {
|
||||||
DefaultDataSourceFactory(requireContext(), USER_AGENT).createDataSource()
|
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()
|
val mediaItemBuilder = MediaItem.Builder()
|
||||||
//Replace needed for android 6.0.0 https://github.com/google/ExoPlayer/issues/5983
|
//Replace needed for android 6.0.0 https://github.com/google/ExoPlayer/issues/5983
|
||||||
.setMimeType(mimeType)
|
.setMimeType(mimeType)
|
||||||
|
|
||||||
if (isOnline) {
|
if (currentUrl != null) {
|
||||||
mediaItemBuilder.setUri(currentUrl.url)
|
mediaItemBuilder.setUri(currentUrl.url)
|
||||||
} else {
|
} else if (uri != null) {
|
||||||
mediaItemBuilder.setUri(Uri.fromFile(File(currentUrl.url)))
|
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()
|
val mediaItem = mediaItemBuilder.build()
|
||||||
|
@ -1401,7 +1458,7 @@ class PlayerFragment : Fragment() {
|
||||||
.setTrackSelector(trackSelector)
|
.setTrackSelector(trackSelector)
|
||||||
|
|
||||||
_exoPlayer.setMediaSourceFactory(DefaultMediaSourceFactory(CustomFactory()))
|
_exoPlayer.setMediaSourceFactory(DefaultMediaSourceFactory(CustomFactory()))
|
||||||
println("START POS: " + playbackPosition)
|
|
||||||
exoPlayer = _exoPlayer.build().apply {
|
exoPlayer = _exoPlayer.build().apply {
|
||||||
playWhenReady = isPlayerPlaying
|
playWhenReady = isPlayerPlaying
|
||||||
seekTo(currentWindow, playbackPosition)
|
seekTo(currentWindow, playbackPosition)
|
||||||
|
@ -1431,24 +1488,38 @@ class PlayerFragment : Fragment() {
|
||||||
exoPlayer.playbackParameters = PlaybackParameters(playbackSpeed)
|
exoPlayer.playbackParameters = PlaybackParameters(playbackSpeed)
|
||||||
player_speed_text?.text = "Speed (${playbackSpeed}x)".replace(".0x", "x")
|
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 data = localData!!
|
||||||
val localEpisode = getEpisode()
|
val localEpisode = getEpisode()
|
||||||
if (localEpisode != null) {
|
if (localEpisode != null) {
|
||||||
val episode = localEpisode.episode
|
epEpisode = localEpisode.episode
|
||||||
val season: Int? = localEpisode.season
|
epSeason = localEpisode.season
|
||||||
val isEpisodeBased = data.isEpisodeBased()
|
hName = data.name
|
||||||
video_title?.text = data.name +
|
isEpisodeBased = data.isEpisodeBased()
|
||||||
if (isEpisodeBased)
|
|
||||||
if (season == null)
|
|
||||||
" - Episode $episode"
|
|
||||||
else
|
|
||||||
" \"S${season}:E${episode}\""
|
|
||||||
else ""
|
|
||||||
video_title_rez?.text = currentUrl.name
|
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,
|
exo_remaining.text = Util.getStringForTime(formatBuilder,
|
||||||
formatter,
|
formatter,
|
||||||
|
@ -1465,8 +1536,10 @@ class PlayerFragment : Fragment() {
|
||||||
|
|
||||||
val height = exoPlayer.videoFormat?.height
|
val height = exoPlayer.videoFormat?.height
|
||||||
val width = exoPlayer.videoFormat?.width
|
val width = exoPlayer.videoFormat?.width
|
||||||
|
|
||||||
video_title_rez?.text =
|
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
|
if (!hasUsedFirstRender) { // DON'T WANT TO SET MULTIPLE MESSAGES
|
||||||
changeSkip()
|
changeSkip()
|
||||||
|
@ -1521,11 +1594,11 @@ class PlayerFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPlayerError(error: ExoPlaybackException) {
|
override fun onPlayerError(error: ExoPlaybackException) {
|
||||||
println("CURRENT URL: " + currentUrl.url)
|
println("CURRENT URL: " + currentUrl?.url ?: uri)
|
||||||
// Lets pray this doesn't spam Toasts :)
|
// Lets pray this doesn't spam Toasts :)
|
||||||
when (error.type) {
|
when (error.type) {
|
||||||
ExoPlaybackException.TYPE_SOURCE -> {
|
ExoPlaybackException.TYPE_SOURCE -> {
|
||||||
if (currentUrl.url != "") {
|
if (currentUrl?.url != "") {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
activity,
|
activity,
|
||||||
"Source error\n" + error.sourceException.message,
|
"Source error\n" + error.sourceException.message,
|
||||||
|
@ -1565,6 +1638,9 @@ class PlayerFragment : Fragment() {
|
||||||
//http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4
|
//http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
private fun initPlayer() {
|
private fun initPlayer() {
|
||||||
|
if (isDownloadedFile) {
|
||||||
|
initPlayer(null, uriData.uri)
|
||||||
|
}
|
||||||
println("INIT PLAYER")
|
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
|
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()
|
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"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
android:background="@color/bitDarkerGrayBackground"
|
android:background="?attr/darkBackground"
|
||||||
android:id="@+id/download_child_root"
|
android:id="@+id/download_child_root"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
@ -9,11 +9,29 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".ui.download.DownloadFragment">
|
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
|
<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"
|
tools:listitem="@layout/download_child_episode"
|
||||||
android:id="@+id/download_child_list"
|
android:id="@+id/download_child_list"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="match_parent">
|
||||||
</androidx.recyclerview.widget.RecyclerView>
|
</androidx.recyclerview.widget.RecyclerView>
|
||||||
</LinearLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
android:id="@+id/download_root"
|
android:id="@+id/download_root"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
@ -7,100 +7,114 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/darkBackground"
|
||||||
tools:context=".ui.download.DownloadFragment">
|
tools:context=".ui.download.DownloadFragment">
|
||||||
<LinearLayout
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:layout_margin="10dp"
|
android:background="?attr/darkBackground"
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
<TextView
|
<!--
|
||||||
android:layout_marginBottom="5dp"
|
For Scroll add to LinearLayout
|
||||||
android:text="@string/download_storage_text"
|
app:layout_scrollFlags="scroll|enterAlways"
|
||||||
android:layout_width="wrap_content"
|
-->
|
||||||
android:layout_height="wrap_content">
|
|
||||||
</TextView>
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_marginBottom="5dp"
|
android:id="@+id/download_storage_appbar"
|
||||||
android:layout_width="fill_parent"
|
android:visibility="gone"
|
||||||
android:layout_height="12dp"
|
android:layout_margin="10dp"
|
||||||
android:orientation="horizontal">
|
android:orientation="vertical"
|
||||||
<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_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
<View
|
<TextView
|
||||||
android:layout_marginEnd="5dp"
|
|
||||||
android:layout_marginTop="5dp"
|
|
||||||
android:layout_marginBottom="5dp"
|
android:layout_marginBottom="5dp"
|
||||||
android:layout_gravity="center_vertical"
|
android:text="@string/download_storage_text"
|
||||||
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_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
|
<View
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:background="?attr/colorPrimary"
|
android:background="?attr/colorPrimary"
|
||||||
android:layout_width="10dp"
|
android:layout_width="10dp"
|
||||||
android:layout_height="10dp"/>
|
android:layout_height="10dp"/>
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/download_app_txt"
|
android:id="@+id/download_app_txt"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
tools:text="App • 30.58GB"
|
tools:text="App • 30.58GB"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
android:textColor="?attr/textColor"
|
android:textColor="?attr/textColor"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"/>
|
||||||
<View
|
<View
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:background="@color/freeStorageColor"
|
android:background="@color/freeStorageColor"
|
||||||
android:layout_width="10dp"
|
android:layout_width="10dp"
|
||||||
android:layout_height="10dp"/>
|
android:layout_height="10dp"/>
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/download_free_txt"
|
android:id="@+id/download_free_txt"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
tools:text="Free • 30.58GB"
|
tools:text="Free • 30.58GB"
|
||||||
android:textColor="?attr/textColor"
|
android:textColor="?attr/textColor"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"/>
|
||||||
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<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:id="@+id/download_list"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
tools:listitem="@layout/download_header_episode"
|
tools:listitem="@layout/download_header_episode"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="match_parent">
|
||||||
</androidx.recyclerview.widget.RecyclerView>
|
</androidx.recyclerview.widget.RecyclerView>
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/text_no_downloads"
|
android:id="@+id/text_no_downloads"
|
||||||
|
@ -115,4 +129,4 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||||
</LinearLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -8,9 +8,7 @@
|
||||||
android:id="@+id/searchRoot"
|
android:id="@+id/searchRoot"
|
||||||
tools:context=".ui.search.SearchFragment"
|
tools:context=".ui.search.SearchFragment"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_marginTop="@dimen/navbarHeight"
|
android:layout_marginTop="@dimen/navbarHeight">
|
||||||
|
|
||||||
android:background="@color/grayBackground">
|
|
||||||
<FrameLayout android:visibility="visible"
|
<FrameLayout android:visibility="visible"
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:background="@drawable/search_background"
|
android:background="@drawable/search_background"
|
||||||
|
|
|
@ -1,23 +1,22 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!--
|
||||||
<item
|
<item
|
||||||
android:id="@+id/navigation_home"
|
android:id="@+id/navigation_home"
|
||||||
android:icon="@drawable/ic_home_black_24dp"
|
android:icon="@drawable/ic_home_black_24dp"
|
||||||
android:title="@string/title_home"/>
|
android:title="@string/title_home"/>
|
||||||
|
-->
|
||||||
<item
|
<item
|
||||||
android:id="@+id/navigation_search"
|
android:id="@+id/navigation_search"
|
||||||
android:icon="@drawable/search_icon"
|
android:icon="@drawable/search_icon"
|
||||||
android:title="@string/title_search"/>
|
android:title="@string/title_search"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/navigation_notifications"
|
android:id="@+id/navigation_downloads"
|
||||||
android:icon="@drawable/netflix_download"
|
android:icon="@drawable/netflix_download"
|
||||||
android:title="@string/title_downloads"/>
|
android:title="@string/title_downloads"/>
|
||||||
<item
|
<item
|
||||||
android:id="@+id/navigation_settings"
|
android:id="@+id/navigation_settings"
|
||||||
android:icon="@drawable/ic_outline_settings_24"
|
android:icon="@drawable/ic_outline_settings_24"
|
||||||
android:title="@string/title_settings"/>
|
android:title="@string/title_settings"/>
|
||||||
|
|
||||||
</menu>
|
</menu>
|
|
@ -18,7 +18,7 @@
|
||||||
tools:layout="@layout/fragment_search"/>
|
tools:layout="@layout/fragment_search"/>
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/navigation_notifications"
|
android:id="@+id/navigation_downloads"
|
||||||
android:name="com.lagradost.cloudstream3.ui.download.DownloadFragment"
|
android:name="com.lagradost.cloudstream3.ui.download.DownloadFragment"
|
||||||
android:label="@string/title_downloads"
|
android:label="@string/title_downloads"
|
||||||
tools:layout="@layout/fragment_downloads"/>
|
tools:layout="@layout/fragment_downloads"/>
|
||||||
|
@ -28,4 +28,11 @@
|
||||||
android:name="com.lagradost.cloudstream3.ui.settings.SettingsFragment"
|
android:name="com.lagradost.cloudstream3.ui.settings.SettingsFragment"
|
||||||
android:label="@string/title_settings"
|
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>
|
</navigation>
|
Loading…
Reference in a new issue