refactor + fixed back crash issue + fixed downloads to redirect to downloads + fixed toast arca + downloads wrap around text

This commit is contained in:
LagradOst 2021-07-30 03:14:53 +02:00
parent db4cdb0ae2
commit 70b7e5c60b
32 changed files with 325 additions and 251 deletions

View File

@ -2,7 +2,10 @@ package com.lagradost.cloudstream3
import android.app.Application
import android.content.Context
import android.widget.Toast
import com.google.auto.service.AutoService
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.utils.Coroutines.runOnMainThread
import org.acra.ReportField
import org.acra.config.CoreConfiguration
import org.acra.config.toast
@ -16,19 +19,24 @@ import kotlin.concurrent.thread
class CustomReportSender : ReportSender {
// Sends all your crashes to google forms
override fun send(context: Context, errorContent: CrashReportData) {
try {
println("Report sent")
val url =
"https://docs.google.com/forms/u/0/d/e/1FAIpQLSeFmyBChi6HF3IkhTVWPiDXJtxt8W0Hf4Agljm_0-0_QuEYFg/formResponse"
val data = mapOf(
"entry.134906550" to errorContent.toJSON()
)
thread {
println("Sending report")
val url =
"https://docs.google.com/forms/u/0/d/e/1FAIpQLSeFmyBChi6HF3IkhTVWPiDXJtxt8W0Hf4Agljm_0-0_QuEYFg/formResponse"
val data = mapOf(
"entry.134906550" to errorContent.toJSON()
)
thread { // to not run it on main thread
normalSafeApiCall {
val post = khttp.post(url, data = data)
println("Report response: $post")
}
} catch (e: Exception) {
println("ERROR SENDING BUG")
}
runOnMainThread { // to run it on main looper
normalSafeApiCall {
Toast.makeText(context, R.string.acra_report_toast, Toast.LENGTH_SHORT).show()
}
}
}
}
@ -59,12 +67,12 @@ class AcraApplication : Application() {
ReportField.STACK_TRACE
)
// removed this due to bug when starting the app, moved it to when it actually crashes
//each plugin you chose above can be configured in a block like this:
toast {
/*toast {
text = getString(R.string.acra_report_toast)
//opening this block automatically enables the plugin.
}
}*/
}
}
}

View File

@ -14,16 +14,24 @@ import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment
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.requestRW
import com.lagradost.cloudstream3.UIHelper.shouldShowPIPMode
import com.lagradost.cloudstream3.APIHolder.apis
import com.lagradost.cloudstream3.utils.UIHelper.checkWrite
import com.lagradost.cloudstream3.utils.UIHelper.getResourceColor
import com.lagradost.cloudstream3.utils.UIHelper.hasPIPPermission
import com.lagradost.cloudstream3.utils.UIHelper.requestRW
import com.lagradost.cloudstream3.utils.UIHelper.shouldShowPIPMode
import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO
import com.lagradost.cloudstream3.ui.download.DownloadChildFragment
import com.lagradost.cloudstream3.ui.download.DownloadFragment
import com.lagradost.cloudstream3.ui.home.HomeFragment
import com.lagradost.cloudstream3.ui.search.SearchFragment
import com.lagradost.cloudstream3.ui.settings.SettingsFragment
import com.lagradost.cloudstream3.utils.AppUtils.loadResult
import com.lagradost.cloudstream3.utils.DataStore.getKey
import com.lagradost.cloudstream3.utils.DataStore.removeKey
import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.fragment_result.*
const val VLC_PACKAGE = "org.videolan.vlc"
@ -90,6 +98,10 @@ class MainActivity : AppCompatActivity() {
navController.navigate(R.id.navigation_downloads, Bundle(), navOptions)
return true
}
if(child is SearchFragment || child is HomeFragment || child is DownloadFragment || child is SettingsFragment) {
this.finish()
return true
}
}
if (currentFragment != null && supportFragmentManager.fragments.size > 2) {
@ -134,12 +146,35 @@ class MainActivity : AppCompatActivity() {
super.onDestroy()
}
override fun onNewIntent(intent: Intent?) {
handleAppIntent(intent)
super.onNewIntent(intent)
}
private fun handleAppIntent(intent: Intent?) {
if (intent == null) return
val str = intent.dataString
if (str != null) {
if (str.startsWith(DOWNLOAD_NAVIGATE_TO)) {
findNavController(R.id.nav_host_fragment).navigate(R.id.navigation_downloads, null, navOptions)
} else {
for (api in apis) {
if (str.startsWith(api.mainUrl)) {
loadResult(str, str, api.name)
break
}
}
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
setContentView(R.layout.activity_main)
val navView: BottomNavigationView = findViewById(R.id.nav_view)
// val navView: BottomNavigationView = findViewById(R.id.nav_view)
//https://stackoverflow.com/questions/52594181/how-to-know-if-user-has-disabled-picture-in-picture-feature-permission
//https://developer.android.com/guide/topics/ui/picture-in-picture
@ -159,7 +194,7 @@ class MainActivity : AppCompatActivity() {
.setPopUpTo(navController.graph.startDestination, false)
.build()
navView.setOnNavigationItemSelectedListener { item ->
nav_view.setOnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.navigation_home -> {
navController.navigate(R.id.navigation_home, null, navOptions)
@ -177,7 +212,7 @@ class MainActivity : AppCompatActivity() {
true
}
navView.itemRippleColor = ColorStateList.valueOf(getResourceColor(R.attr.colorPrimary, 0.1f))
nav_view.itemRippleColor = ColorStateList.valueOf(getResourceColor(R.attr.colorPrimary, 0.1f))
if (!checkWrite()) {
requestRW()
@ -244,5 +279,7 @@ class MainActivity : AppCompatActivity() {
}
}
}*/
handleAppIntent(intent)
}
}

View File

@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.extractors.Vidstream
import com.lagradost.cloudstream3.extractors.Vidstream
import java.net.URLEncoder
import java.util.*
import kotlin.collections.ArrayList

View File

@ -2,7 +2,7 @@ package com.lagradost.cloudstream3.animeproviders
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.extractors.WcoStream
import com.lagradost.cloudstream3.extractors.WcoStream
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import java.util.*

View File

@ -1,4 +1,4 @@
package com.lagradost.cloudstream3.utils.extractors
package com.lagradost.cloudstream3.extractors
//{"auto":"/manifests/movies/15559/1624728920/qDwu5BOsfAwfTmnnjmkmXA/master.m3u8","1080p":"https://vdoc3.sallenes.space/qDwu5BOsfAwfTmnnjmkmXA/1624728920/storage6/movies/the-man-with-the-iron-heart-2017/1080p/index.m3u8","720p":"https://vdoc3.sallenes.space/qDwu5BOsfAwfTmnnjmkmXA/1624728920/storage6/movies/the-man-with-the-iron-heart-2017/720p/index.m3u8","360p":"https://vdoc3.sallenes.space/qDwu5BOsfAwfTmnnjmkmXA/1624728920/storage6/movies/the-man-with-the-iron-heart-2017/360p/index.m3u8","480p":"https://vdoc3.sallenes.space/qDwu5BOsfAwfTmnnjmkmXA/1624728920/storage6/movies/the-man-with-the-iron-heart-2017/480p/index.m3u8"}
object M3u8Manifest {

View File

@ -1,4 +1,4 @@
package com.lagradost.cloudstream3.utils.extractors
package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.utils.*

View File

@ -1,4 +1,4 @@
package com.lagradost.cloudstream3.utils.extractors
package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.utils.*

View File

@ -1,4 +1,4 @@
package com.lagradost.cloudstream3.utils.extractors
package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink

View File

@ -1,4 +1,4 @@
package com.lagradost.cloudstream3.utils.extractors
package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink

View File

@ -1,4 +1,4 @@
package com.lagradost.cloudstream3.utils.extractors
package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink

View File

@ -1,4 +1,4 @@
package com.lagradost.cloudstream3.utils.extractors
package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink

View File

@ -1,4 +1,4 @@
package com.lagradost.cloudstream3.utils.extractors
package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.pmap
import com.lagradost.cloudstream3.utils.ExtractorLink

View File

@ -1,4 +1,4 @@
package com.lagradost.cloudstream3.utils.extractors
package com.lagradost.cloudstream3.extractors
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.readValue

View File

@ -1,4 +1,4 @@
package com.lagradost.cloudstream3.utils.extractors
package com.lagradost.cloudstream3.extractors
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.readValue

View File

@ -5,7 +5,7 @@ import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.APIHolder.unixTime
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.extractors.M3u8Manifest
import com.lagradost.cloudstream3.extractors.M3u8Manifest
import com.lagradost.cloudstream3.utils.getQualityFromName
import org.jsoup.Jsoup

View File

@ -7,12 +7,11 @@ import android.view.View
import android.widget.LinearLayout
import android.widget.ProgressBar
import android.widget.RelativeLayout
import androidx.core.content.ContextCompat
import com.google.android.gms.cast.framework.media.widget.MiniControllerFragment
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.UIHelper.adjustAlpha
import com.lagradost.cloudstream3.UIHelper.colorFromAttribute
import com.lagradost.cloudstream3.UIHelper.toPx
import com.lagradost.cloudstream3.utils.UIHelper.adjustAlpha
import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute
import com.lagradost.cloudstream3.utils.UIHelper.toPx
class MyMiniControllerFragment : MiniControllerFragment() {

View File

@ -117,6 +117,8 @@ class DownloadChildAdapter(
}
title.text = d.name ?: "Episode ${d.episode}" //TODO FIX
title.isSelected = true // is needed for text repeating
downloadButton.setUpButton(
card.currentBytes,
card.totalBytes,

View File

@ -8,7 +8,7 @@ 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.utils.UIHelper.fixPaddingStatusbar
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
import com.lagradost.cloudstream3.utils.Coroutines.main
import com.lagradost.cloudstream3.utils.DataStore.getKey

View File

@ -12,7 +12,7 @@ import androidx.navigation.findNavController
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.utils.UIHelper.fixPaddingStatusbar
import com.lagradost.cloudstream3.isMovieType
import com.lagradost.cloudstream3.mvvm.observe
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
@ -21,6 +21,8 @@ import com.lagradost.cloudstream3.utils.DataStore.getFolderName
import com.lagradost.cloudstream3.utils.VideoDownloadManager
import kotlinx.android.synthetic.main.fragment_downloads.*
const val DOWNLOAD_NAVIGATE_TO = "downloadpage"
class DownloadFragment : Fragment() {
private lateinit var downloadsViewModel: DownloadViewModel

View File

@ -9,7 +9,7 @@ import android.widget.TextView
import androidx.core.widget.ContentLoadingProgressBar
import com.google.android.material.button.MaterialButton
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.UIHelper.popupMenuNoIcons
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIcons
import com.lagradost.cloudstream3.utils.Coroutines
import com.lagradost.cloudstream3.utils.IDisposable
import com.lagradost.cloudstream3.utils.VideoDownloadHelper

View File

@ -22,15 +22,15 @@ import com.lagradost.cloudstream3.AnimeSearchResponse
import com.lagradost.cloudstream3.HomePageResponse
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.SearchResponse
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
import com.lagradost.cloudstream3.UIHelper.getGridIsCompact
import com.lagradost.cloudstream3.UIHelper.loadSearchResult
import com.lagradost.cloudstream3.UIHelper.popupMenuNoIconsAndNoStringRes
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIconsAndNoStringRes
import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.mvvm.observe
import com.lagradost.cloudstream3.ui.AutofitRecyclerView
import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST
import com.lagradost.cloudstream3.ui.search.SearchAdapter
import com.lagradost.cloudstream3.utils.AppUtils.loadSearchResult
import com.lagradost.cloudstream3.utils.DataStore.getKey
import com.lagradost.cloudstream3.utils.DataStore.setKey
import com.lagradost.cloudstream3.utils.Event

View File

@ -57,27 +57,29 @@ import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.MainActivity.Companion.isInPIPMode
import com.lagradost.cloudstream3.MainActivity.Companion.isInPlayer
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.UIHelper.getFocusRequest
import com.lagradost.cloudstream3.UIHelper.getNavigationBarHeight
import com.lagradost.cloudstream3.UIHelper.getStatusBarHeight
import com.lagradost.cloudstream3.UIHelper.hideKeyboard
import com.lagradost.cloudstream3.UIHelper.hideSystemUI
import com.lagradost.cloudstream3.UIHelper.isCastApiAvailable
import com.lagradost.cloudstream3.UIHelper.popCurrentPage
import com.lagradost.cloudstream3.UIHelper.requestLocalAudioFocus
import com.lagradost.cloudstream3.UIHelper.showSystemUI
import com.lagradost.cloudstream3.UIHelper.toPx
import com.lagradost.cloudstream3.utils.UIHelper.getNavigationBarHeight
import com.lagradost.cloudstream3.utils.UIHelper.getStatusBarHeight
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
import com.lagradost.cloudstream3.utils.UIHelper.hideSystemUI
import com.lagradost.cloudstream3.utils.UIHelper.popCurrentPage
import com.lagradost.cloudstream3.utils.UIHelper.showSystemUI
import com.lagradost.cloudstream3.utils.UIHelper.toPx
import com.lagradost.cloudstream3.mvvm.Resource
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.getFocusRequest
import com.lagradost.cloudstream3.utils.AppUtils.getVideoContentUri
import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable
import com.lagradost.cloudstream3.utils.AppUtils.onAudioFocusEvent
import com.lagradost.cloudstream3.utils.AppUtils.requestLocalAudioFocus
import com.lagradost.cloudstream3.utils.CastHelper.startCast
import com.lagradost.cloudstream3.utils.DataStore.getKey
import com.lagradost.cloudstream3.utils.DataStore.setKey
import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.UIHelper
import com.lagradost.cloudstream3.utils.VIDEO_PLAYER_BRIGHTNESS
import com.lagradost.cloudstream3.utils.getId
import kotlinx.android.synthetic.main.fragment_player.*
@ -1283,7 +1285,7 @@ class PlayerFragment : Fragment() {
override fun onResume() {
super.onResume()
UIHelper.onAudioFocusEvent += ::handlePauseEvent
onAudioFocusEvent += ::handlePauseEvent
activity?.hideSystemUI()
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
@ -1310,7 +1312,7 @@ class PlayerFragment : Fragment() {
savePositionInPlayer()
safeReleasePlayer()
UIHelper.onAudioFocusEvent -= ::handlePauseEvent
onAudioFocusEvent -= ::handlePauseEvent
activity?.showSystemUI()
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER

View File

@ -34,28 +34,28 @@ import com.google.android.material.button.MaterialButton
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.APIHolder.getApiFromName
import com.lagradost.cloudstream3.APIHolder.getId
import com.lagradost.cloudstream3.UIHelper.checkWrite
import com.lagradost.cloudstream3.UIHelper.colorFromAttribute
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
import com.lagradost.cloudstream3.UIHelper.getStatusBarHeight
import com.lagradost.cloudstream3.UIHelper.hideKeyboard
import com.lagradost.cloudstream3.UIHelper.isAppInstalled
import com.lagradost.cloudstream3.UIHelper.isCastApiAvailable
import com.lagradost.cloudstream3.UIHelper.isConnectedToChromecast
import com.lagradost.cloudstream3.UIHelper.popCurrentPage
import com.lagradost.cloudstream3.UIHelper.popupMenuNoIcons
import com.lagradost.cloudstream3.UIHelper.popupMenuNoIconsAndNoStringRes
import com.lagradost.cloudstream3.UIHelper.requestRW
import com.lagradost.cloudstream3.utils.UIHelper.checkWrite
import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
import com.lagradost.cloudstream3.utils.UIHelper.getStatusBarHeight
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
import com.lagradost.cloudstream3.utils.UIHelper.popCurrentPage
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIcons
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIconsAndNoStringRes
import com.lagradost.cloudstream3.utils.UIHelper.requestRW
import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.mvvm.observe
import com.lagradost.cloudstream3.ui.WatchType
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO
import com.lagradost.cloudstream3.ui.download.EasyDownloadButton
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
import com.lagradost.cloudstream3.ui.player.PlayerData
import com.lagradost.cloudstream3.ui.player.PlayerFragment
import com.lagradost.cloudstream3.utils.*
import com.lagradost.cloudstream3.utils.AppUtils.isAppInstalled
import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable
import com.lagradost.cloudstream3.utils.AppUtils.isConnectedToChromecast
import com.lagradost.cloudstream3.utils.CastHelper.startCast
import com.lagradost.cloudstream3.utils.Coroutines.main
import com.lagradost.cloudstream3.utils.DataStore.getFolderName
@ -422,12 +422,16 @@ class ResultFragment : Fragment() {
}
context?.let { ctx ->
val parentId = currentId ?: return@let
val src = "$DOWNLOAD_NAVIGATE_TO/$parentId" // url ?: return@let
// SET VISUAL KEYS
ctx.setKey(
DOWNLOAD_HEADER_CACHE, (currentId ?: return@let).toString(),
DOWNLOAD_HEADER_CACHE, parentId.toString(),
VideoDownloadHelper.DownloadHeaderCached(
apiName,
url ?: return@let,
slug ?: return@let,
currentType ?: return@let,
currentHeaderName ?: return@let,
currentPoster ?: return@let,
@ -439,7 +443,7 @@ class ResultFragment : Fragment() {
ctx.setKey(
getFolderName(
DOWNLOAD_EPISODE_CACHE,
(currentId ?: return@let).toString()
parentId.toString()
), // 3 deep folder for faster acess
epData.id.toString(),
VideoDownloadHelper.DownloadEpisodeCached(
@ -448,7 +452,7 @@ class ResultFragment : Fragment() {
epData.episode,
epData.season,
epData.id,
currentId ?: return@let,
parentId,
epData.rating,
epData.descript
)
@ -457,7 +461,7 @@ class ResultFragment : Fragment() {
// DOWNLOAD VIDEO
VideoDownloadManager.downloadEpisode(
ctx,
url ?: return,
src,//url ?: return,
folder,
meta,
links

View File

@ -14,9 +14,9 @@ import com.lagradost.cloudstream3.AnimeSearchResponse
import com.lagradost.cloudstream3.DubStatus
import com.lagradost.cloudstream3.SearchResponse
import com.lagradost.cloudstream3.TvType
import com.lagradost.cloudstream3.UIHelper.getGridFormatId
import com.lagradost.cloudstream3.UIHelper.getGridIsCompact
import com.lagradost.cloudstream3.UIHelper.toPx
import com.lagradost.cloudstream3.utils.UIHelper.getGridFormatId
import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact
import com.lagradost.cloudstream3.utils.UIHelper.toPx
import com.lagradost.cloudstream3.ui.AutofitRecyclerView
import kotlinx.android.synthetic.main.search_result_compact.view.backgroundCard
import kotlinx.android.synthetic.main.search_result_compact.view.imageText

View File

@ -11,7 +11,6 @@ import android.view.inputmethod.InputMethodManager
import android.widget.ImageView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
@ -21,12 +20,11 @@ import com.lagradost.cloudstream3.APIHolder.allApi
import com.lagradost.cloudstream3.APIHolder.apis
import com.lagradost.cloudstream3.APIHolder.getApiSettings
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
import com.lagradost.cloudstream3.UIHelper.getGridIsCompact
import com.lagradost.cloudstream3.UIHelper.loadResult
import com.lagradost.cloudstream3.UIHelper.loadSearchResult
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact
import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.mvvm.observe
import com.lagradost.cloudstream3.utils.AppUtils.loadSearchResult
import kotlinx.android.synthetic.main.fragment_search.*
class SearchFragment : Fragment() {
@ -167,6 +165,7 @@ class SearchFragment : Fragment() {
}
}
main_search.onActionViewExpanded()
val q = 0 / 0
//searchViewModel.search("iron man")
//(activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro")
/*

View File

@ -1,9 +1,28 @@
package com.lagradost.cloudstream3.utils
import android.app.Activity
import android.content.ContentValues
import android.content.Context
import android.content.pm.PackageManager
import android.media.AudioAttributes
import android.media.AudioFocusRequest
import android.media.AudioManager
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.net.Uri
import android.os.Build
import android.provider.MediaStore
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.PreferenceManager
import com.google.android.gms.cast.framework.CastContext
import com.google.android.gms.cast.framework.CastState
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import com.google.android.gms.common.wrappers.Wrappers
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.SearchResponse
import com.lagradost.cloudstream3.ui.result.ResultFragment
object AppUtils {
fun getVideoContentUri(context: Context, videoFilePath: String): Uri? {
@ -23,4 +42,117 @@ object AppUtils {
)
}
}
fun AppCompatActivity.loadResult(url: String, slug: String, apiName: String, startAction: Int = 0) {
this.runOnUiThread {
viewModelStore.clear()
this.supportFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim, R.anim.pop_enter, R.anim.pop_exit)
.add(R.id.homeRoot, ResultFragment.newInstance(url, slug, apiName, startAction))
.commit()
}
}
fun Activity?.loadSearchResult(card: SearchResponse, startAction: Int = 0) {
(this as AppCompatActivity?)?.loadResult(card.url, card.slug, card.apiName, startAction)
}
fun Activity.requestLocalAudioFocus(focusRequest: AudioFocusRequest?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && focusRequest != null) {
val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
audioManager.requestAudioFocus(focusRequest)
} else {
val audioManager: AudioManager =
getSystemService(Context.AUDIO_SERVICE) as AudioManager
audioManager.requestAudioFocus(
null,
AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
)
}
}
private var currentAudioFocusRequest: AudioFocusRequest? = null
private var currentAudioFocusChangeListener: AudioManager.OnAudioFocusChangeListener? = null
var onAudioFocusEvent = Event<Boolean>()
private fun getAudioListener(): AudioManager.OnAudioFocusChangeListener? {
if (currentAudioFocusChangeListener != null) return currentAudioFocusChangeListener
currentAudioFocusChangeListener = AudioManager.OnAudioFocusChangeListener {
onAudioFocusEvent.invoke(
when (it) {
AudioManager.AUDIOFOCUS_GAIN -> false
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE -> false
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT -> false
else -> true
}
)
}
return currentAudioFocusChangeListener
}
fun Context.isCastApiAvailable(): Boolean {
val isCastApiAvailable =
GoogleApiAvailability.getInstance()
.isGooglePlayServicesAvailable(applicationContext) == ConnectionResult.SUCCESS
try {
applicationContext?.let { CastContext.getSharedInstance(it) }
} catch (e: Exception) {
println(e)
// track non-fatal
return false
}
return isCastApiAvailable
}
fun Context.isConnectedToChromecast(): Boolean {
if (isCastApiAvailable()) {
val castContext = CastContext.getSharedInstance(this)
if (castContext.castState == CastState.CONNECTED) {
return true
}
}
return false
}
fun Context.isUsingMobileData(): Boolean {
val conManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkInfo = conManager.allNetworks
return networkInfo.any {
conManager.getNetworkCapabilities(it)?.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) == true
}
}
fun Context.isAppInstalled(uri: String): Boolean {
val pm = Wrappers.packageManager(this)
var appInstalled = false
appInstalled = try {
pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES)
true
} catch (e: PackageManager.NameNotFoundException) {
false
}
return appInstalled
}
fun getFocusRequest(): AudioFocusRequest? {
if (currentAudioFocusRequest != null) return currentAudioFocusRequest
currentAudioFocusRequest = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).run {
setAudioAttributes(AudioAttributes.Builder().run {
setUsage(AudioAttributes.USAGE_MEDIA)
setContentType(AudioAttributes.CONTENT_TYPE_MOVIE)
build()
})
setAcceptsDelayedFocusGain(true)
getAudioListener()?.let {
setOnAudioFocusChangeListener(it)
}
build()
}
} else {
null
}
return currentAudioFocusRequest
}
}

View File

@ -1,5 +1,6 @@
package com.lagradost.cloudstream3.utils
import com.lagradost.cloudstream3.extractors.*
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.utils.extractors.*

View File

@ -1,4 +1,4 @@
package com.lagradost.cloudstream3
package com.lagradost.cloudstream3.utils
import android.Manifest
import android.annotation.SuppressLint
@ -11,8 +11,6 @@ import android.graphics.Color
import android.media.AudioAttributes
import android.media.AudioFocusRequest
import android.media.AudioManager
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
import android.view.Gravity
import android.view.MenuItem
@ -21,7 +19,6 @@ 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
import androidx.appcompat.view.menu.MenuBuilder
import androidx.appcompat.widget.PopupMenu
@ -34,13 +31,7 @@ import androidx.core.graphics.red
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.preference.PreferenceManager
import com.google.android.gms.cast.framework.CastContext
import com.google.android.gms.cast.framework.CastState
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import com.google.android.gms.common.wrappers.Wrappers.packageManager
import com.lagradost.cloudstream3.ui.result.ResultFragment
import com.lagradost.cloudstream3.utils.Event
import com.lagradost.cloudstream3.R
import kotlin.math.roundToInt
@ -91,137 +82,6 @@ object UIHelper {
return color
}
fun AppCompatActivity.loadResult(url: String, slug: String, apiName: String, startAction: Int = 0) {
this.runOnUiThread {
viewModelStore.clear()
this.supportFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim, R.anim.pop_enter, R.anim.pop_exit)
.add(R.id.homeRoot, ResultFragment.newInstance(url, slug, apiName, startAction))
.commit()
}
}
fun Activity?.loadSearchResult(card: SearchResponse, startAction: Int = 0) {
(this as AppCompatActivity?)?.loadResult(card.url, card.slug, card.apiName, startAction)
}
fun Context.getStatusBarHeight(): Int {
var result = 0
val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
if (resourceId > 0) {
result = resources.getDimensionPixelSize(resourceId)
}
return result
}
fun Context.getNavigationBarHeight(): Int {
var result = 0
val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
if (resourceId > 0) {
result = resources.getDimensionPixelSize(resourceId)
}
return result
}
fun Context.fixPaddingStatusbar(v: View) {
v.setPadding(v.paddingLeft, v.paddingTop + getStatusBarHeight(), v.paddingRight, v.paddingBottom)
}
private fun Context.getGridFormat(): String {
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
return settingsManager.getString(getString(R.string.grid_format_key), "grid")!!
}
fun Context.getGridFormatId(): Int {
return when (getGridFormat()) {
"list" -> R.layout.search_result_compact
"compact_list" -> R.layout.search_result_super_compact
else -> R.layout.search_result_grid
}
}
fun Context.getGridIsCompact(): Boolean {
return getGridFormat() != "grid"
}
fun Activity.requestLocalAudioFocus(focusRequest: AudioFocusRequest?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && focusRequest != null) {
val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
audioManager.requestAudioFocus(focusRequest)
} else {
val audioManager: AudioManager =
getSystemService(Context.AUDIO_SERVICE) as AudioManager
audioManager.requestAudioFocus(
null,
AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
)
}
}
private var currentAudioFocusRequest: AudioFocusRequest? = null
private var currentAudioFocusChangeListener: AudioManager.OnAudioFocusChangeListener? = null
var onAudioFocusEvent = Event<Boolean>()
private fun getAudioListener(): AudioManager.OnAudioFocusChangeListener? {
if (currentAudioFocusChangeListener != null) return currentAudioFocusChangeListener
currentAudioFocusChangeListener = AudioManager.OnAudioFocusChangeListener {
onAudioFocusEvent.invoke(
when (it) {
AudioManager.AUDIOFOCUS_GAIN -> false
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE -> false
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT -> false
else -> true
}
)
}
return currentAudioFocusChangeListener
}
fun Context.isCastApiAvailable(): Boolean {
val isCastApiAvailable =
GoogleApiAvailability.getInstance()
.isGooglePlayServicesAvailable(applicationContext) == ConnectionResult.SUCCESS
try {
applicationContext?.let { CastContext.getSharedInstance(it) }
} catch (e: Exception) {
println(e)
// track non-fatal
return false
}
return isCastApiAvailable
}
fun Context.isConnectedToChromecast(): Boolean {
if (isCastApiAvailable()) {
val castContext = CastContext.getSharedInstance(this)
if (castContext.castState == CastState.CONNECTED) {
return true
}
}
return false
}
fun Context.isUsingMobileData(): Boolean {
val conManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkInfo = conManager.allNetworks
return networkInfo.any {
conManager.getNetworkCapabilities(it)?.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) == true
}
}
fun Context.isAppInstalled(uri: String): Boolean {
val pm = packageManager(this)
var appInstalled = false
appInstalled = try {
pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES)
true
} catch (e: PackageManager.NameNotFoundException) {
false
}
return appInstalled
}
fun adjustAlpha(@ColorInt color: Int, factor: Float): Int {
val alpha = (Color.alpha(color) * factor).roundToInt()
val red = Color.red(color)
@ -237,27 +97,6 @@ object UIHelper {
return color
}
fun getFocusRequest(): AudioFocusRequest? {
if (currentAudioFocusRequest != null) return currentAudioFocusRequest
currentAudioFocusRequest = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).run {
setAudioAttributes(AudioAttributes.Builder().run {
setUsage(AudioAttributes.USAGE_MEDIA)
setContentType(AudioAttributes.CONTENT_TYPE_MOVIE)
build()
})
setAcceptsDelayedFocusGain(true)
getAudioListener()?.let {
setOnAudioFocusChangeListener(it)
}
build()
}
} else {
null
}
return currentAudioFocusRequest
}
fun Activity.hideSystemUI() {
// Enables regular immersive mode.
// For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE.
@ -337,6 +176,43 @@ object UIHelper {
}
}*/
fun Context.getStatusBarHeight(): Int {
var result = 0
val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
if (resourceId > 0) {
result = resources.getDimensionPixelSize(resourceId)
}
return result
}
fun Context.fixPaddingStatusbar(v: View) {
v.setPadding(v.paddingLeft, v.paddingTop + getStatusBarHeight(), v.paddingRight, v.paddingBottom)
}
fun Context.getNavigationBarHeight(): Int {
var result = 0
val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
if (resourceId > 0) {
result = resources.getDimensionPixelSize(resourceId)
}
return result
}
private fun Context.getGridFormat(): String {
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
return settingsManager.getString(getString(R.string.grid_format_key), "grid")!!
}
fun Context.getGridFormatId(): Int {
return when (getGridFormat()) {
"list" -> R.layout.search_result_compact
"compact_list" -> R.layout.search_result_super_compact
else -> R.layout.search_result_grid
}
}
fun Context.getGridIsCompact(): Boolean {
return getGridFormat() != "grid"
}
fun Activity.changeStatusBarState(hide: Boolean): Int {
return if (hide) {

View File

@ -16,7 +16,8 @@ object VideoDownloadHelper {
data class DownloadHeaderCached(
val apiName: String,
val source: String,
val url: String,
val slug : String,
val type : TvType,
val name: String,
val poster: String?,

View File

@ -19,7 +19,7 @@ import androidx.core.net.toUri
import com.bumptech.glide.Glide
import com.lagradost.cloudstream3.MainActivity
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.UIHelper.colorFromAttribute
import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute
import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.services.VideoDownloadService

View File

@ -17,6 +17,7 @@
android:layout_height="wrap_content"
android:background="@color/darkBackground"
app:itemRippleColor="@color/colorRipple"
app:labelVisibilityMode="labeled"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"

View File

@ -36,14 +36,24 @@
android:layout_gravity="center_vertical"
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginEnd="50dp"
android:layout_width="match_parent"
>
<TextView
android:id="@+id/download_child_episode_text"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_gravity="center_vertical" android:gravity="center_vertical" tools:text="Episode 1"
android:textColor="@color/textColor" android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
tools:text="Episode 1 Episode 1 Episode 1 Episode 1 Episode 1 Episode 1 Episode 1"
android:scrollHorizontally="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
android:textColor="@color/textColor"
android:layout_width="match_parent"
android:layout_height="match_parent">
</TextView>
<TextView
@ -57,9 +67,9 @@
android:layout_width="wrap_content"
android:layout_height="match_parent">
</TextView>
</LinearLayout>
<FrameLayout
android:layout_marginStart="-50dp"
android:layout_gravity="end"
android:layout_width="wrap_content"
android:layout_height="match_parent">