forked from recloudstream/cloudstream
Add webview fallback for TV
This commit is contained in:
parent
309c2b828c
commit
ef165ad4cb
8 changed files with 149 additions and 37 deletions
|
@ -3,6 +3,7 @@ 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 android.widget.Toast
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
import com.google.auto.service.AutoService
|
import com.google.auto.service.AutoService
|
||||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||||
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
|
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
|
||||||
|
@ -135,8 +136,11 @@ class AcraApplication : Application() {
|
||||||
context?.removeKey(path)
|
context?.removeKey(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun openBrowser(url: String) {
|
/**
|
||||||
context?.openBrowser(url)
|
* If fallbackWebview is true and a fragment is supplied then it will open a webview with the url if the browser fails.
|
||||||
|
* */
|
||||||
|
fun openBrowser(url: String, fallbackWebview: Boolean = false, fragment: Fragment? = null) {
|
||||||
|
context?.openBrowser(url, fallbackWebview, fragment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -82,11 +82,9 @@ import java.io.File
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import com.lagradost.cloudstream3.plugins.PluginManager
|
import com.lagradost.cloudstream3.plugins.PluginManager
|
||||||
import com.lagradost.cloudstream3.plugins.RepositoryManager
|
|
||||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringRepo
|
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringRepo
|
||||||
import com.lagradost.cloudstream3.ui.settings.extensions.RepositoryData
|
|
||||||
import com.lagradost.cloudstream3.ui.setup.SetupFragmentExtensions
|
import com.lagradost.cloudstream3.ui.setup.SetupFragmentExtensions
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
import com.lagradost.cloudstream3.utils.AppUtils.loadRepository
|
||||||
import com.lagradost.cloudstream3.utils.Event
|
import com.lagradost.cloudstream3.utils.Event
|
||||||
|
|
||||||
|
|
||||||
|
@ -332,26 +330,6 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
super.onNewIntent(intent)
|
super.onNewIntent(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadRepo(url: String) {
|
|
||||||
ioSafe {
|
|
||||||
val repo = RepositoryManager.parseRepository(url) ?: return@ioSafe
|
|
||||||
RepositoryManager.addRepository(
|
|
||||||
RepositoryData(
|
|
||||||
repo.name,
|
|
||||||
url
|
|
||||||
)
|
|
||||||
)
|
|
||||||
main {
|
|
||||||
showToast(
|
|
||||||
this@MainActivity,
|
|
||||||
getString(R.string.player_loaded_subtitles, repo.name),
|
|
||||||
Toast.LENGTH_LONG
|
|
||||||
)
|
|
||||||
}
|
|
||||||
afterRepositoryLoadedEvent.invoke(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleAppIntent(intent: Intent?) {
|
private fun handleAppIntent(intent: Intent?) {
|
||||||
if (intent == null) return
|
if (intent == null) return
|
||||||
val str = intent.dataString
|
val str = intent.dataString
|
||||||
|
@ -360,7 +338,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
if (str.startsWith("https://cs.repo")) {
|
if (str.startsWith("https://cs.repo")) {
|
||||||
val realUrl = "https://" + str.substringAfter("?")
|
val realUrl = "https://" + str.substringAfter("?")
|
||||||
println("Repository url: $realUrl")
|
println("Repository url: $realUrl")
|
||||||
loadRepo(realUrl)
|
loadRepository(realUrl)
|
||||||
} else if (str.contains(appString)) {
|
} else if (str.contains(appString)) {
|
||||||
for (api in OAuth2Apis) {
|
for (api in OAuth2Apis) {
|
||||||
if (str.contains("/${api.redirectUrl}")) {
|
if (str.contains("/${api.redirectUrl}")) {
|
||||||
|
@ -392,7 +370,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
}
|
}
|
||||||
} else if (str.contains(appStringRepo)) {
|
} else if (str.contains(appStringRepo)) {
|
||||||
val url = str.replaceFirst(appStringRepo, "https")
|
val url = str.replaceFirst(appStringRepo, "https")
|
||||||
loadRepo(url)
|
loadRepository(url)
|
||||||
} else {
|
} else {
|
||||||
if (str.startsWith(DOWNLOAD_NAVIGATE_TO)) {
|
if (str.startsWith(DOWNLOAD_NAVIGATE_TO)) {
|
||||||
this.navigate(R.id.navigation_downloads)
|
this.navigate(R.id.navigation_downloads)
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
package com.lagradost.cloudstream3.ui
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.webkit.WebResourceRequest
|
||||||
|
import android.webkit.WebView
|
||||||
|
import android.webkit.WebViewClient
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.USER_AGENT
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.loadRepository
|
||||||
|
import kotlinx.android.synthetic.main.fragment_webview.*
|
||||||
|
|
||||||
|
class WebviewFragment : Fragment() {
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
val url = arguments?.getString(WEBVIEW_URL) ?: "".also {
|
||||||
|
findNavController().popBackStack()
|
||||||
|
}
|
||||||
|
|
||||||
|
web_view.webViewClient = object : WebViewClient() {
|
||||||
|
override fun shouldOverrideUrlLoading(
|
||||||
|
view: WebView?,
|
||||||
|
request: WebResourceRequest?
|
||||||
|
): Boolean {
|
||||||
|
val requestUrl = request?.url.toString()
|
||||||
|
if (requestUrl.startsWith("https://cs.repo")) {
|
||||||
|
val realUrl = "https://" + requestUrl.substringAfter("?")
|
||||||
|
println("Repository url: $realUrl :::: $requestUrl")
|
||||||
|
activity?.loadRepository(realUrl)
|
||||||
|
findNavController().popBackStack()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.shouldOverrideUrlLoading(view, request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
web_view.settings.javaScriptEnabled = true
|
||||||
|
web_view.settings.domStorageEnabled = true
|
||||||
|
web_view.settings.userAgentString = USER_AGENT
|
||||||
|
web_view.loadUrl(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
// Inflate the layout for this fragment
|
||||||
|
return inflater.inflate(R.layout.fragment_webview, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val WEBVIEW_URL = "webview_url"
|
||||||
|
fun newInstance(webViewUrl: String) =
|
||||||
|
Bundle().apply {
|
||||||
|
putString(WEBVIEW_URL, webViewUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -119,10 +119,12 @@ class ExtensionsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
list_repositories?.setOnClickListener {
|
list_repositories?.setOnClickListener {
|
||||||
openBrowser(PUBLIC_REPOSITORIES_LIST)
|
// Open webview on tv if browser fails
|
||||||
|
val isTv = it.context.isTvSettings()
|
||||||
|
openBrowser(PUBLIC_REPOSITORIES_LIST, isTv, this)
|
||||||
|
|
||||||
// Set clipboard on TV because the browser might not exist or work properly
|
// Set clipboard on TV because the browser might not exist or work properly
|
||||||
if (it.context.isTvSettings()) {
|
if (isTv) {
|
||||||
val serviceClipboard =
|
val serviceClipboard =
|
||||||
(activity?.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager?)
|
(activity?.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager?)
|
||||||
?: return@setOnClickListener
|
?: return@setOnClickListener
|
||||||
|
@ -189,7 +191,9 @@ class ExtensionsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.list_repositories?.setOnClickListener {
|
dialog.list_repositories?.setOnClickListener {
|
||||||
openBrowser(PUBLIC_REPOSITORIES_LIST)
|
// Open webview on tv if browser fails
|
||||||
|
val isTv = it.context.isTvSettings()
|
||||||
|
openBrowser(PUBLIC_REPOSITORIES_LIST, isTv, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
// dialog.text2?.text = provider.name
|
// dialog.text2?.text = provider.name
|
||||||
|
|
|
@ -12,6 +12,7 @@ import com.lagradost.cloudstream3.MainActivity.Companion.afterRepositoryLoadedEv
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.plugins.RepositoryManager
|
import com.lagradost.cloudstream3.plugins.RepositoryManager
|
||||||
import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIES
|
import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIES
|
||||||
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||||
import com.lagradost.cloudstream3.ui.settings.extensions.PUBLIC_REPOSITORIES_LIST
|
import com.lagradost.cloudstream3.ui.settings.extensions.PUBLIC_REPOSITORIES_LIST
|
||||||
import com.lagradost.cloudstream3.ui.settings.extensions.PluginsViewModel
|
import com.lagradost.cloudstream3.ui.settings.extensions.PluginsViewModel
|
||||||
import com.lagradost.cloudstream3.ui.settings.extensions.RepoAdapter
|
import com.lagradost.cloudstream3.ui.settings.extensions.RepoAdapter
|
||||||
|
@ -65,7 +66,9 @@ class SetupFragmentExtensions : Fragment() {
|
||||||
}).apply { updateList(repositories) }
|
}).apply { updateList(repositories) }
|
||||||
} else {
|
} else {
|
||||||
list_repositories?.setOnClickListener {
|
list_repositories?.setOnClickListener {
|
||||||
openBrowser(PUBLIC_REPOSITORIES_LIST)
|
// Open webview on tv if browser fails
|
||||||
|
val isTv = it.context.isTvSettings()
|
||||||
|
openBrowser(PUBLIC_REPOSITORIES_LIST, isTv, this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +90,6 @@ class SetupFragmentExtensions : Fragment() {
|
||||||
|
|
||||||
next_btt?.setOnClickListener {
|
next_btt?.setOnClickListener {
|
||||||
// Continue setup
|
// Continue setup
|
||||||
println("ISSETUP $isSetup")
|
|
||||||
if (isSetup)
|
if (isSetup)
|
||||||
findNavController().navigate(R.id.action_navigation_setup_extensions_to_navigation_setup_provider_languages)
|
findNavController().navigate(R.id.action_navigation_setup_extensions_to_navigation_setup_provider_languages)
|
||||||
else
|
else
|
||||||
|
|
|
@ -20,12 +20,15 @@ import android.os.ParcelFileDescriptor
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.text.Spanned
|
import android.text.Spanned
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.text.HtmlCompat
|
import androidx.core.text.HtmlCompat
|
||||||
import androidx.core.text.toSpanned
|
import androidx.core.text.toSpanned
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.tvprovider.media.tv.PreviewChannelHelper
|
import androidx.tvprovider.media.tv.PreviewChannelHelper
|
||||||
|
@ -38,16 +41,20 @@ import com.google.android.gms.cast.framework.CastState
|
||||||
import com.google.android.gms.common.ConnectionResult
|
import com.google.android.gms.common.ConnectionResult
|
||||||
import com.google.android.gms.common.GoogleApiAvailability
|
import com.google.android.gms.common.GoogleApiAvailability
|
||||||
import com.google.android.gms.common.wrappers.Wrappers
|
import com.google.android.gms.common.wrappers.Wrappers
|
||||||
|
import com.lagradost.cloudstream3.CommonActivity.showToast
|
||||||
|
import com.lagradost.cloudstream3.MainActivity.Companion.afterRepositoryLoadedEvent
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.SearchResponse
|
import com.lagradost.cloudstream3.SearchResponse
|
||||||
import com.lagradost.cloudstream3.isMovieType
|
import com.lagradost.cloudstream3.isMovieType
|
||||||
import com.lagradost.cloudstream3.mapper
|
import com.lagradost.cloudstream3.mapper
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
|
import com.lagradost.cloudstream3.plugins.RepositoryManager
|
||||||
|
import com.lagradost.cloudstream3.ui.WebviewFragment
|
||||||
import com.lagradost.cloudstream3.ui.result.ResultFragment
|
import com.lagradost.cloudstream3.ui.result.ResultFragment
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
import com.lagradost.cloudstream3.ui.settings.extensions.RepositoryData
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.loadResult
|
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||||
|
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||||
import com.lagradost.cloudstream3.utils.FillerEpisodeCheck.toClassDir
|
import com.lagradost.cloudstream3.utils.FillerEpisodeCheck.toClassDir
|
||||||
import com.lagradost.cloudstream3.utils.JsUnpacker.Companion.load
|
import com.lagradost.cloudstream3.utils.JsUnpacker.Companion.load
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
||||||
|
@ -232,8 +239,35 @@ object AppUtils {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fun Activity.loadRepository(url: String) {
|
||||||
|
ioSafe {
|
||||||
|
val repo = RepositoryManager.parseRepository(url) ?: return@ioSafe
|
||||||
|
RepositoryManager.addRepository(
|
||||||
|
RepositoryData(
|
||||||
|
repo.name,
|
||||||
|
url
|
||||||
|
)
|
||||||
|
)
|
||||||
|
main {
|
||||||
|
showToast(
|
||||||
|
this@loadRepository,
|
||||||
|
getString(R.string.player_loaded_subtitles, repo.name),
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
)
|
||||||
|
}
|
||||||
|
afterRepositoryLoadedEvent.invoke(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun Context.openBrowser(url: String) {
|
|
||||||
|
/**
|
||||||
|
* If fallbackWebview is true and a fragment is supplied then it will open a webview with the url if the browser fails.
|
||||||
|
* */
|
||||||
|
fun Context.openBrowser(
|
||||||
|
url: String,
|
||||||
|
fallbackWebview: Boolean = false,
|
||||||
|
fragment: Fragment? = null
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
val intent = Intent(Intent.ACTION_VIEW)
|
val intent = Intent(Intent.ACTION_VIEW)
|
||||||
intent.data = Uri.parse(url)
|
intent.data = Uri.parse(url)
|
||||||
|
@ -241,6 +275,15 @@ object AppUtils {
|
||||||
ContextCompat.startActivity(this, intent, null)
|
ContextCompat.startActivity(this, intent, null)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logError(e)
|
logError(e)
|
||||||
|
if (fallbackWebview) {
|
||||||
|
try {
|
||||||
|
fragment
|
||||||
|
?.findNavController()
|
||||||
|
?.navigate(R.id.navigation_webview, WebviewFragment.newInstance(url))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,8 +359,8 @@ object AppUtils {
|
||||||
|
|
||||||
//private val viewModel: ResultViewModel by activityViewModels()
|
//private val viewModel: ResultViewModel by activityViewModels()
|
||||||
|
|
||||||
private fun getResultsId(context: Context) : Int {
|
private fun getResultsId(context: Context): Int {
|
||||||
return if(context.isTrueTvSettings()) {
|
return if (context.isTrueTvSettings()) {
|
||||||
R.id.global_to_navigation_results_tv
|
R.id.global_to_navigation_results_tv
|
||||||
} else {
|
} else {
|
||||||
R.id.global_to_navigation_results_phone
|
R.id.global_to_navigation_results_phone
|
||||||
|
|
9
app/src/main/res/layout/fragment_webview.xml
Normal file
9
app/src/main/res/layout/fragment_webview.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/web_view"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".ui.WebviewFragment">
|
||||||
|
|
||||||
|
</WebView>
|
|
@ -194,6 +194,16 @@
|
||||||
app:popExitAnim="@anim/exit_anim"
|
app:popExitAnim="@anim/exit_anim"
|
||||||
tools:layout="@layout/fragment_plugins" />
|
tools:layout="@layout/fragment_plugins" />
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/navigation_webview"
|
||||||
|
android:name="com.lagradost.cloudstream3.ui.WebviewFragment"
|
||||||
|
android:label="@string/title_settings"
|
||||||
|
app:enterAnim="@anim/enter_anim"
|
||||||
|
app:exitAnim="@anim/exit_anim"
|
||||||
|
app:popEnterAnim="@anim/enter_anim"
|
||||||
|
app:popExitAnim="@anim/exit_anim"
|
||||||
|
tools:layout="@layout/fragment_webview" />
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/navigation_settings_lang"
|
android:id="@+id/navigation_settings_lang"
|
||||||
android:name="com.lagradost.cloudstream3.ui.settings.SettingsLang"
|
android:name="com.lagradost.cloudstream3.ui.settings.SettingsLang"
|
||||||
|
|
Loading…
Reference in a new issue