diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt index 1a8fd9bb..d5d1f878 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt @@ -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() diff --git a/app/src/main/java/com/lagradost/cloudstream3/UIHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/UIHelper.kt index db491765..6b0ab221 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/UIHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/UIHelper.kt @@ -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() diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildFragment.kt index 37b0ee82..19478747 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildFragment.kt @@ -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 = 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 diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadFragment.kt index b70ab6b7..2aafaa08 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadFragment.kt @@ -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 diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt index f090e6b3..72f4a2b2 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt @@ -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() diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/AppUtils.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/AppUtils.kt new file mode 100644 index 00000000..8b06e0d9 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/AppUtils.kt @@ -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 + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_child_downloads.xml b/app/src/main/res/layout/fragment_child_downloads.xml index 06fa0c43..82e247e2 100644 --- a/app/src/main/res/layout/fragment_child_downloads.xml +++ b/app/src/main/res/layout/fragment_child_downloads.xml @@ -1,6 +1,6 @@ - + + + + + + android:layout_height="match_parent"> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_downloads.xml b/app/src/main/res/layout/fragment_downloads.xml index f1cefb49..dcac53b1 100644 --- a/app/src/main/res/layout/fragment_downloads.xml +++ b/app/src/main/res/layout/fragment_downloads.xml @@ -1,5 +1,5 @@ - - - - + - - - - - - - + android:layout_height="wrap_content"> + + + + + + + + + - - - - + + + + + - + + android:layout_height="match_parent"> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml index 4001aa7a..4e62cd6d 100644 --- a/app/src/main/res/layout/fragment_search.xml +++ b/app/src/main/res/layout/fragment_search.xml @@ -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"> - + - \ No newline at end of file diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml index 0397df29..806e93f4 100644 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ b/app/src/main/res/navigation/mobile_navigation.xml @@ -18,7 +18,7 @@ tools:layout="@layout/fragment_search"/> @@ -28,4 +28,11 @@ android:name="com.lagradost.cloudstream3.ui.settings.SettingsFragment" android:label="@string/title_settings" /> + + \ No newline at end of file