downloads playable

This commit is contained in:
LagradOst 2021-07-19 15:19:47 +02:00
parent 3bf76a9563
commit 5ffb53bf1c
11 changed files with 405 additions and 175 deletions

View File

@ -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()

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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
)
}
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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"

View File

@ -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>

View File

@ -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>