forked from recloudstream/cloudstream
refactor + fixed back crash issue + fixed downloads to redirect to downloads + fixed toast arca + downloads wrap around text
This commit is contained in:
parent
db4cdb0ae2
commit
70b7e5c60b
32 changed files with 325 additions and 251 deletions
|
@ -2,7 +2,10 @@ package com.lagradost.cloudstream3
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.widget.Toast
|
||||||
import com.google.auto.service.AutoService
|
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.ReportField
|
||||||
import org.acra.config.CoreConfiguration
|
import org.acra.config.CoreConfiguration
|
||||||
import org.acra.config.toast
|
import org.acra.config.toast
|
||||||
|
@ -16,19 +19,24 @@ import kotlin.concurrent.thread
|
||||||
class CustomReportSender : ReportSender {
|
class CustomReportSender : ReportSender {
|
||||||
// Sends all your crashes to google forms
|
// Sends all your crashes to google forms
|
||||||
override fun send(context: Context, errorContent: CrashReportData) {
|
override fun send(context: Context, errorContent: CrashReportData) {
|
||||||
try {
|
println("Sending report")
|
||||||
println("Report sent")
|
val url =
|
||||||
val url =
|
"https://docs.google.com/forms/u/0/d/e/1FAIpQLSeFmyBChi6HF3IkhTVWPiDXJtxt8W0Hf4Agljm_0-0_QuEYFg/formResponse"
|
||||||
"https://docs.google.com/forms/u/0/d/e/1FAIpQLSeFmyBChi6HF3IkhTVWPiDXJtxt8W0Hf4Agljm_0-0_QuEYFg/formResponse"
|
val data = mapOf(
|
||||||
val data = mapOf(
|
"entry.134906550" to errorContent.toJSON()
|
||||||
"entry.134906550" to errorContent.toJSON()
|
)
|
||||||
)
|
|
||||||
thread {
|
thread { // to not run it on main thread
|
||||||
|
normalSafeApiCall {
|
||||||
val post = khttp.post(url, data = data)
|
val post = khttp.post(url, data = data)
|
||||||
println("Report response: $post")
|
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
|
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:
|
//each plugin you chose above can be configured in a block like this:
|
||||||
toast {
|
/*toast {
|
||||||
text = getString(R.string.acra_report_toast)
|
text = getString(R.string.acra_report_toast)
|
||||||
//opening this block automatically enables the plugin.
|
//opening this block automatically enables the plugin.
|
||||||
}
|
}*/
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,16 +14,24 @@ import androidx.navigation.findNavController
|
||||||
import androidx.navigation.fragment.NavHostFragment
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
import com.google.android.gms.cast.framework.CastButtonFactory
|
import com.google.android.gms.cast.framework.CastButtonFactory
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
import com.lagradost.cloudstream3.UIHelper.checkWrite
|
import com.lagradost.cloudstream3.APIHolder.apis
|
||||||
import com.lagradost.cloudstream3.UIHelper.getResourceColor
|
import com.lagradost.cloudstream3.utils.UIHelper.checkWrite
|
||||||
import com.lagradost.cloudstream3.UIHelper.hasPIPPermission
|
import com.lagradost.cloudstream3.utils.UIHelper.getResourceColor
|
||||||
import com.lagradost.cloudstream3.UIHelper.requestRW
|
import com.lagradost.cloudstream3.utils.UIHelper.hasPIPPermission
|
||||||
import com.lagradost.cloudstream3.UIHelper.shouldShowPIPMode
|
import com.lagradost.cloudstream3.utils.UIHelper.requestRW
|
||||||
|
import com.lagradost.cloudstream3.utils.UIHelper.shouldShowPIPMode
|
||||||
import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver
|
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.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.getKey
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.removeKey
|
import com.lagradost.cloudstream3.utils.DataStore.removeKey
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos
|
||||||
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
import kotlinx.android.synthetic.main.fragment_result.*
|
import kotlinx.android.synthetic.main.fragment_result.*
|
||||||
|
|
||||||
const val VLC_PACKAGE = "org.videolan.vlc"
|
const val VLC_PACKAGE = "org.videolan.vlc"
|
||||||
|
@ -90,6 +98,10 @@ class MainActivity : AppCompatActivity() {
|
||||||
navController.navigate(R.id.navigation_downloads, Bundle(), navOptions)
|
navController.navigate(R.id.navigation_downloads, Bundle(), navOptions)
|
||||||
return true
|
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) {
|
if (currentFragment != null && supportFragmentManager.fragments.size > 2) {
|
||||||
|
@ -134,12 +146,35 @@ class MainActivity : AppCompatActivity() {
|
||||||
super.onDestroy()
|
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?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
|
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
|
||||||
|
|
||||||
setContentView(R.layout.activity_main)
|
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://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
|
//https://developer.android.com/guide/topics/ui/picture-in-picture
|
||||||
|
@ -159,7 +194,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
.setPopUpTo(navController.graph.startDestination, false)
|
.setPopUpTo(navController.graph.startDestination, false)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
navView.setOnNavigationItemSelectedListener { item ->
|
nav_view.setOnNavigationItemSelectedListener { item ->
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.navigation_home -> {
|
R.id.navigation_home -> {
|
||||||
navController.navigate(R.id.navigation_home, null, navOptions)
|
navController.navigate(R.id.navigation_home, null, navOptions)
|
||||||
|
@ -177,7 +212,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
navView.itemRippleColor = ColorStateList.valueOf(getResourceColor(R.attr.colorPrimary, 0.1f))
|
nav_view.itemRippleColor = ColorStateList.valueOf(getResourceColor(R.attr.colorPrimary, 0.1f))
|
||||||
|
|
||||||
if (!checkWrite()) {
|
if (!checkWrite()) {
|
||||||
requestRW()
|
requestRW()
|
||||||
|
@ -244,5 +279,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
handleAppIntent(intent)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
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.net.URLEncoder
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
|
@ -2,7 +2,7 @@ package com.lagradost.cloudstream3.animeproviders
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
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.Jsoup
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
|
@ -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"}
|
//{"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 {
|
object M3u8Manifest {
|
|
@ -1,4 +1,4 @@
|
||||||
package com.lagradost.cloudstream3.utils.extractors
|
package com.lagradost.cloudstream3.extractors
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.utils.*
|
import com.lagradost.cloudstream3.utils.*
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.lagradost.cloudstream3.utils.extractors
|
package com.lagradost.cloudstream3.extractors
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.utils.*
|
import com.lagradost.cloudstream3.utils.*
|
||||||
|
|
|
@ -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.ExtractorApi
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
@ -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.ExtractorApi
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
@ -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.ExtractorApi
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
@ -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.ExtractorApi
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
@ -1,4 +1,4 @@
|
||||||
package com.lagradost.cloudstream3.utils.extractors
|
package com.lagradost.cloudstream3.extractors
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.pmap
|
import com.lagradost.cloudstream3.pmap
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
@ -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.annotation.JsonProperty
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
import com.fasterxml.jackson.module.kotlin.readValue
|
|
@ -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.annotation.JsonProperty
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
import com.fasterxml.jackson.module.kotlin.readValue
|
|
@ -5,7 +5,7 @@ import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.APIHolder.unixTime
|
import com.lagradost.cloudstream3.APIHolder.unixTime
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
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 com.lagradost.cloudstream3.utils.getQualityFromName
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,11 @@ import android.view.View
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.ProgressBar
|
import android.widget.ProgressBar
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import com.google.android.gms.cast.framework.media.widget.MiniControllerFragment
|
import com.google.android.gms.cast.framework.media.widget.MiniControllerFragment
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.UIHelper.adjustAlpha
|
import com.lagradost.cloudstream3.utils.UIHelper.adjustAlpha
|
||||||
import com.lagradost.cloudstream3.UIHelper.colorFromAttribute
|
import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute
|
||||||
import com.lagradost.cloudstream3.UIHelper.toPx
|
import com.lagradost.cloudstream3.utils.UIHelper.toPx
|
||||||
|
|
||||||
|
|
||||||
class MyMiniControllerFragment : MiniControllerFragment() {
|
class MyMiniControllerFragment : MiniControllerFragment() {
|
||||||
|
|
|
@ -117,6 +117,8 @@ class DownloadChildAdapter(
|
||||||
}
|
}
|
||||||
|
|
||||||
title.text = d.name ?: "Episode ${d.episode}" //TODO FIX
|
title.text = d.name ?: "Episode ${d.episode}" //TODO FIX
|
||||||
|
title.isSelected = true // is needed for text repeating
|
||||||
|
|
||||||
downloadButton.setUpButton(
|
downloadButton.setUpButton(
|
||||||
card.currentBytes,
|
card.currentBytes,
|
||||||
card.totalBytes,
|
card.totalBytes,
|
||||||
|
|
|
@ -8,7 +8,7 @@ import androidx.fragment.app.Fragment
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||||
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
|
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||||
|
|
|
@ -12,7 +12,7 @@ import androidx.navigation.findNavController
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.R
|
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.isMovieType
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
|
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 com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||||
import kotlinx.android.synthetic.main.fragment_downloads.*
|
import kotlinx.android.synthetic.main.fragment_downloads.*
|
||||||
|
|
||||||
|
const val DOWNLOAD_NAVIGATE_TO = "downloadpage"
|
||||||
|
|
||||||
class DownloadFragment : Fragment() {
|
class DownloadFragment : Fragment() {
|
||||||
private lateinit var downloadsViewModel: DownloadViewModel
|
private lateinit var downloadsViewModel: DownloadViewModel
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import android.widget.TextView
|
||||||
import androidx.core.widget.ContentLoadingProgressBar
|
import androidx.core.widget.ContentLoadingProgressBar
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.lagradost.cloudstream3.R
|
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.Coroutines
|
||||||
import com.lagradost.cloudstream3.utils.IDisposable
|
import com.lagradost.cloudstream3.utils.IDisposable
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||||
|
|
|
@ -22,15 +22,15 @@ import com.lagradost.cloudstream3.AnimeSearchResponse
|
||||||
import com.lagradost.cloudstream3.HomePageResponse
|
import com.lagradost.cloudstream3.HomePageResponse
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.SearchResponse
|
import com.lagradost.cloudstream3.SearchResponse
|
||||||
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||||
import com.lagradost.cloudstream3.UIHelper.getGridIsCompact
|
import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact
|
||||||
import com.lagradost.cloudstream3.UIHelper.loadSearchResult
|
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIconsAndNoStringRes
|
||||||
import com.lagradost.cloudstream3.UIHelper.popupMenuNoIconsAndNoStringRes
|
|
||||||
import com.lagradost.cloudstream3.mvvm.Resource
|
import com.lagradost.cloudstream3.mvvm.Resource
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
import com.lagradost.cloudstream3.ui.AutofitRecyclerView
|
import com.lagradost.cloudstream3.ui.AutofitRecyclerView
|
||||||
import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST
|
import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST
|
||||||
import com.lagradost.cloudstream3.ui.search.SearchAdapter
|
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.getKey
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
||||||
import com.lagradost.cloudstream3.utils.Event
|
import com.lagradost.cloudstream3.utils.Event
|
||||||
|
|
|
@ -57,27 +57,29 @@ import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.MainActivity.Companion.isInPIPMode
|
import com.lagradost.cloudstream3.MainActivity.Companion.isInPIPMode
|
||||||
import com.lagradost.cloudstream3.MainActivity.Companion.isInPlayer
|
import com.lagradost.cloudstream3.MainActivity.Companion.isInPlayer
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.UIHelper.getFocusRequest
|
import com.lagradost.cloudstream3.utils.UIHelper.getNavigationBarHeight
|
||||||
import com.lagradost.cloudstream3.UIHelper.getNavigationBarHeight
|
import com.lagradost.cloudstream3.utils.UIHelper.getStatusBarHeight
|
||||||
import com.lagradost.cloudstream3.UIHelper.getStatusBarHeight
|
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
|
||||||
import com.lagradost.cloudstream3.UIHelper.hideKeyboard
|
import com.lagradost.cloudstream3.utils.UIHelper.hideSystemUI
|
||||||
import com.lagradost.cloudstream3.UIHelper.hideSystemUI
|
import com.lagradost.cloudstream3.utils.UIHelper.popCurrentPage
|
||||||
import com.lagradost.cloudstream3.UIHelper.isCastApiAvailable
|
import com.lagradost.cloudstream3.utils.UIHelper.showSystemUI
|
||||||
import com.lagradost.cloudstream3.UIHelper.popCurrentPage
|
import com.lagradost.cloudstream3.utils.UIHelper.toPx
|
||||||
import com.lagradost.cloudstream3.UIHelper.requestLocalAudioFocus
|
|
||||||
import com.lagradost.cloudstream3.UIHelper.showSystemUI
|
|
||||||
import com.lagradost.cloudstream3.UIHelper.toPx
|
|
||||||
import com.lagradost.cloudstream3.mvvm.Resource
|
import com.lagradost.cloudstream3.mvvm.Resource
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
import com.lagradost.cloudstream3.mvvm.observeDirectly
|
import com.lagradost.cloudstream3.mvvm.observeDirectly
|
||||||
import com.lagradost.cloudstream3.ui.result.ResultEpisode
|
import com.lagradost.cloudstream3.ui.result.ResultEpisode
|
||||||
import com.lagradost.cloudstream3.ui.result.ResultViewModel
|
import com.lagradost.cloudstream3.ui.result.ResultViewModel
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.getFocusRequest
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.getVideoContentUri
|
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.CastHelper.startCast
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
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.VIDEO_PLAYER_BRIGHTNESS
|
||||||
import com.lagradost.cloudstream3.utils.getId
|
import com.lagradost.cloudstream3.utils.getId
|
||||||
import kotlinx.android.synthetic.main.fragment_player.*
|
import kotlinx.android.synthetic.main.fragment_player.*
|
||||||
|
@ -1283,7 +1285,7 @@ class PlayerFragment : Fragment() {
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
UIHelper.onAudioFocusEvent += ::handlePauseEvent
|
onAudioFocusEvent += ::handlePauseEvent
|
||||||
|
|
||||||
activity?.hideSystemUI()
|
activity?.hideSystemUI()
|
||||||
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
|
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
|
||||||
|
@ -1310,7 +1312,7 @@ class PlayerFragment : Fragment() {
|
||||||
savePositionInPlayer()
|
savePositionInPlayer()
|
||||||
safeReleasePlayer()
|
safeReleasePlayer()
|
||||||
|
|
||||||
UIHelper.onAudioFocusEvent -= ::handlePauseEvent
|
onAudioFocusEvent -= ::handlePauseEvent
|
||||||
|
|
||||||
activity?.showSystemUI()
|
activity?.showSystemUI()
|
||||||
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER
|
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER
|
||||||
|
|
|
@ -34,28 +34,28 @@ import com.google.android.material.button.MaterialButton
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.APIHolder.getApiFromName
|
import com.lagradost.cloudstream3.APIHolder.getApiFromName
|
||||||
import com.lagradost.cloudstream3.APIHolder.getId
|
import com.lagradost.cloudstream3.APIHolder.getId
|
||||||
import com.lagradost.cloudstream3.UIHelper.checkWrite
|
import com.lagradost.cloudstream3.utils.UIHelper.checkWrite
|
||||||
import com.lagradost.cloudstream3.UIHelper.colorFromAttribute
|
import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute
|
||||||
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||||
import com.lagradost.cloudstream3.UIHelper.getStatusBarHeight
|
import com.lagradost.cloudstream3.utils.UIHelper.getStatusBarHeight
|
||||||
import com.lagradost.cloudstream3.UIHelper.hideKeyboard
|
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
|
||||||
import com.lagradost.cloudstream3.UIHelper.isAppInstalled
|
import com.lagradost.cloudstream3.utils.UIHelper.popCurrentPage
|
||||||
import com.lagradost.cloudstream3.UIHelper.isCastApiAvailable
|
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIcons
|
||||||
import com.lagradost.cloudstream3.UIHelper.isConnectedToChromecast
|
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIconsAndNoStringRes
|
||||||
import com.lagradost.cloudstream3.UIHelper.popCurrentPage
|
import com.lagradost.cloudstream3.utils.UIHelper.requestRW
|
||||||
import com.lagradost.cloudstream3.UIHelper.popupMenuNoIcons
|
|
||||||
import com.lagradost.cloudstream3.UIHelper.popupMenuNoIconsAndNoStringRes
|
|
||||||
import com.lagradost.cloudstream3.UIHelper.requestRW
|
|
||||||
import com.lagradost.cloudstream3.mvvm.Resource
|
import com.lagradost.cloudstream3.mvvm.Resource
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
import com.lagradost.cloudstream3.ui.WatchType
|
import com.lagradost.cloudstream3.ui.WatchType
|
||||||
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD
|
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.EasyDownloadButton
|
||||||
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup
|
|
||||||
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
|
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
|
||||||
import com.lagradost.cloudstream3.ui.player.PlayerData
|
import com.lagradost.cloudstream3.ui.player.PlayerData
|
||||||
import com.lagradost.cloudstream3.ui.player.PlayerFragment
|
import com.lagradost.cloudstream3.ui.player.PlayerFragment
|
||||||
import com.lagradost.cloudstream3.utils.*
|
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.CastHelper.startCast
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getFolderName
|
import com.lagradost.cloudstream3.utils.DataStore.getFolderName
|
||||||
|
@ -422,12 +422,16 @@ class ResultFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
context?.let { ctx ->
|
context?.let { ctx ->
|
||||||
|
val parentId = currentId ?: return@let
|
||||||
|
val src = "$DOWNLOAD_NAVIGATE_TO/$parentId" // url ?: return@let
|
||||||
|
|
||||||
// SET VISUAL KEYS
|
// SET VISUAL KEYS
|
||||||
ctx.setKey(
|
ctx.setKey(
|
||||||
DOWNLOAD_HEADER_CACHE, (currentId ?: return@let).toString(),
|
DOWNLOAD_HEADER_CACHE, parentId.toString(),
|
||||||
VideoDownloadHelper.DownloadHeaderCached(
|
VideoDownloadHelper.DownloadHeaderCached(
|
||||||
apiName,
|
apiName,
|
||||||
url ?: return@let,
|
url ?: return@let,
|
||||||
|
slug ?: return@let,
|
||||||
currentType ?: return@let,
|
currentType ?: return@let,
|
||||||
currentHeaderName ?: return@let,
|
currentHeaderName ?: return@let,
|
||||||
currentPoster ?: return@let,
|
currentPoster ?: return@let,
|
||||||
|
@ -439,7 +443,7 @@ class ResultFragment : Fragment() {
|
||||||
ctx.setKey(
|
ctx.setKey(
|
||||||
getFolderName(
|
getFolderName(
|
||||||
DOWNLOAD_EPISODE_CACHE,
|
DOWNLOAD_EPISODE_CACHE,
|
||||||
(currentId ?: return@let).toString()
|
parentId.toString()
|
||||||
), // 3 deep folder for faster acess
|
), // 3 deep folder for faster acess
|
||||||
epData.id.toString(),
|
epData.id.toString(),
|
||||||
VideoDownloadHelper.DownloadEpisodeCached(
|
VideoDownloadHelper.DownloadEpisodeCached(
|
||||||
|
@ -448,7 +452,7 @@ class ResultFragment : Fragment() {
|
||||||
epData.episode,
|
epData.episode,
|
||||||
epData.season,
|
epData.season,
|
||||||
epData.id,
|
epData.id,
|
||||||
currentId ?: return@let,
|
parentId,
|
||||||
epData.rating,
|
epData.rating,
|
||||||
epData.descript
|
epData.descript
|
||||||
)
|
)
|
||||||
|
@ -457,7 +461,7 @@ class ResultFragment : Fragment() {
|
||||||
// DOWNLOAD VIDEO
|
// DOWNLOAD VIDEO
|
||||||
VideoDownloadManager.downloadEpisode(
|
VideoDownloadManager.downloadEpisode(
|
||||||
ctx,
|
ctx,
|
||||||
url ?: return,
|
src,//url ?: return,
|
||||||
folder,
|
folder,
|
||||||
meta,
|
meta,
|
||||||
links
|
links
|
||||||
|
|
|
@ -14,9 +14,9 @@ import com.lagradost.cloudstream3.AnimeSearchResponse
|
||||||
import com.lagradost.cloudstream3.DubStatus
|
import com.lagradost.cloudstream3.DubStatus
|
||||||
import com.lagradost.cloudstream3.SearchResponse
|
import com.lagradost.cloudstream3.SearchResponse
|
||||||
import com.lagradost.cloudstream3.TvType
|
import com.lagradost.cloudstream3.TvType
|
||||||
import com.lagradost.cloudstream3.UIHelper.getGridFormatId
|
import com.lagradost.cloudstream3.utils.UIHelper.getGridFormatId
|
||||||
import com.lagradost.cloudstream3.UIHelper.getGridIsCompact
|
import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact
|
||||||
import com.lagradost.cloudstream3.UIHelper.toPx
|
import com.lagradost.cloudstream3.utils.UIHelper.toPx
|
||||||
import com.lagradost.cloudstream3.ui.AutofitRecyclerView
|
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.backgroundCard
|
||||||
import kotlinx.android.synthetic.main.search_result_compact.view.imageText
|
import kotlinx.android.synthetic.main.search_result_compact.view.imageText
|
||||||
|
|
|
@ -11,7 +11,6 @@ import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
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.apis
|
||||||
import com.lagradost.cloudstream3.APIHolder.getApiSettings
|
import com.lagradost.cloudstream3.APIHolder.getApiSettings
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||||
import com.lagradost.cloudstream3.UIHelper.getGridIsCompact
|
import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact
|
||||||
import com.lagradost.cloudstream3.UIHelper.loadResult
|
|
||||||
import com.lagradost.cloudstream3.UIHelper.loadSearchResult
|
|
||||||
import com.lagradost.cloudstream3.mvvm.Resource
|
import com.lagradost.cloudstream3.mvvm.Resource
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.loadSearchResult
|
||||||
import kotlinx.android.synthetic.main.fragment_search.*
|
import kotlinx.android.synthetic.main.fragment_search.*
|
||||||
|
|
||||||
class SearchFragment : Fragment() {
|
class SearchFragment : Fragment() {
|
||||||
|
@ -167,6 +165,7 @@ class SearchFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
main_search.onActionViewExpanded()
|
main_search.onActionViewExpanded()
|
||||||
|
val q = 0 / 0
|
||||||
//searchViewModel.search("iron man")
|
//searchViewModel.search("iron man")
|
||||||
//(activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro")
|
//(activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro")
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,9 +1,28 @@
|
||||||
package com.lagradost.cloudstream3.utils
|
package com.lagradost.cloudstream3.utils
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.content.Context
|
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.net.Uri
|
||||||
|
import android.os.Build
|
||||||
import android.provider.MediaStore
|
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 {
|
object AppUtils {
|
||||||
fun getVideoContentUri(context: Context, videoFilePath: String): Uri? {
|
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
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package com.lagradost.cloudstream3.utils
|
package com.lagradost.cloudstream3.utils
|
||||||
|
|
||||||
|
import com.lagradost.cloudstream3.extractors.*
|
||||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||||
import com.lagradost.cloudstream3.utils.extractors.*
|
import com.lagradost.cloudstream3.utils.extractors.*
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.lagradost.cloudstream3
|
package com.lagradost.cloudstream3.utils
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
@ -11,8 +11,6 @@ import android.graphics.Color
|
||||||
import android.media.AudioAttributes
|
import android.media.AudioAttributes
|
||||||
import android.media.AudioFocusRequest
|
import android.media.AudioFocusRequest
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
import android.net.ConnectivityManager
|
|
||||||
import android.net.NetworkCapabilities
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
|
@ -21,7 +19,6 @@ import android.view.WindowManager
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import androidx.annotation.AttrRes
|
import androidx.annotation.AttrRes
|
||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.appcompat.view.ContextThemeWrapper
|
import androidx.appcompat.view.ContextThemeWrapper
|
||||||
import androidx.appcompat.view.menu.MenuBuilder
|
import androidx.appcompat.view.menu.MenuBuilder
|
||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
|
@ -34,13 +31,7 @@ import androidx.core.graphics.red
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.google.android.gms.cast.framework.CastContext
|
import com.lagradost.cloudstream3.R
|
||||||
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 kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,137 +82,6 @@ object UIHelper {
|
||||||
return color
|
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 {
|
fun adjustAlpha(@ColorInt color: Int, factor: Float): Int {
|
||||||
val alpha = (Color.alpha(color) * factor).roundToInt()
|
val alpha = (Color.alpha(color) * factor).roundToInt()
|
||||||
val red = Color.red(color)
|
val red = Color.red(color)
|
||||||
|
@ -237,27 +97,6 @@ object UIHelper {
|
||||||
return color
|
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() {
|
fun Activity.hideSystemUI() {
|
||||||
// Enables regular immersive mode.
|
// Enables regular immersive mode.
|
||||||
// For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE.
|
// 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 {
|
fun Activity.changeStatusBarState(hide: Boolean): Int {
|
||||||
return if (hide) {
|
return if (hide) {
|
|
@ -16,7 +16,8 @@ object VideoDownloadHelper {
|
||||||
|
|
||||||
data class DownloadHeaderCached(
|
data class DownloadHeaderCached(
|
||||||
val apiName: String,
|
val apiName: String,
|
||||||
val source: String,
|
val url: String,
|
||||||
|
val slug : String,
|
||||||
val type : TvType,
|
val type : TvType,
|
||||||
val name: String,
|
val name: String,
|
||||||
val poster: String?,
|
val poster: String?,
|
||||||
|
|
|
@ -19,7 +19,7 @@ import androidx.core.net.toUri
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.lagradost.cloudstream3.MainActivity
|
import com.lagradost.cloudstream3.MainActivity
|
||||||
import com.lagradost.cloudstream3.R
|
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.logError
|
||||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||||
import com.lagradost.cloudstream3.services.VideoDownloadService
|
import com.lagradost.cloudstream3.services.VideoDownloadService
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/darkBackground"
|
android:background="@color/darkBackground"
|
||||||
app:itemRippleColor="@color/colorRipple"
|
app:itemRippleColor="@color/colorRipple"
|
||||||
|
app:labelVisibilityMode="labeled"
|
||||||
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
|
|
@ -36,14 +36,24 @@
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_marginEnd="50dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
>
|
>
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/download_child_episode_text"
|
android:id="@+id/download_child_episode_text"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:layout_gravity="center_vertical" android:gravity="center_vertical" tools:text="Episode 1"
|
android:layout_gravity="center_vertical"
|
||||||
android:textColor="@color/textColor" android:layout_width="wrap_content"
|
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">
|
android:layout_height="match_parent">
|
||||||
</TextView>
|
</TextView>
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -57,9 +67,9 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
</TextView>
|
</TextView>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
|
android:layout_marginStart="-50dp"
|
||||||
android:layout_gravity="end"
|
android:layout_gravity="end"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
Loading…
Reference in a new issue