diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt index 85b3b363..6f01e055 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt @@ -11,6 +11,9 @@ import android.view.Menu import android.view.MenuItem import android.view.WindowManager import android.widget.Toast +import androidx.activity.result.ActivityResult +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.IdRes import androidx.appcompat.app.AppCompatActivity import androidx.core.view.isVisible @@ -33,6 +36,7 @@ import com.lagradost.cloudstream3.APIHolder.apis import com.lagradost.cloudstream3.APIHolder.getApiDubstatusSettings import com.lagradost.cloudstream3.APIHolder.initAll import com.lagradost.cloudstream3.APIHolder.updateHasTrailers +import com.lagradost.cloudstream3.CommonActivity.currentToast import com.lagradost.cloudstream3.CommonActivity.loadThemes import com.lagradost.cloudstream3.CommonActivity.onColorSelectedEvent import com.lagradost.cloudstream3.CommonActivity.onDialogDismissedEvent @@ -85,7 +89,10 @@ import com.lagradost.cloudstream3.plugins.PluginManager import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringRepo import com.lagradost.cloudstream3.ui.setup.SetupFragmentExtensions import com.lagradost.cloudstream3.utils.AppUtils.loadRepository +import com.lagradost.cloudstream3.utils.Coroutines.main import com.lagradost.cloudstream3.utils.Event +import kotlinx.coroutines.delay +import java.lang.ref.WeakReference const val VLC_PACKAGE = "org.videolan.vlc" @@ -293,7 +300,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - if (VLC_REQUEST_CODE == requestCode) { + if (requestCode == VLC_REQUEST_CODE) { if (resultCode == RESULT_OK && data != null) { val pos: Long = data.getLongExtra( @@ -677,13 +684,25 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { && PluginManager.getPluginsLocal().isEmpty() // && PREBUILT_REPOSITORIES.isNotEmpty() ) { - navController.navigate(R.id.navigation_setup_extensions, SetupFragmentExtensions.newInstance(false)) + navController.navigate( + R.id.navigation_setup_extensions, + SetupFragmentExtensions.newInstance(false) + ) } } catch (e: Exception) { logError(e) } finally { setKey(HAS_DONE_SETUP_KEY, true) } + +// Used to check current focus for TV +// main { +// while (true) { +// delay(1000) +// println("Current focus: $currentFocus") +// } +// } + /* val relativePath = (Environment.DIRECTORY_DOWNLOADS) + File.separatorChar diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt index 74230638..d841deaa 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt @@ -60,8 +60,7 @@ import com.lagradost.cloudstream3.utils.DataStoreHelper.deleteAllResumeStateIds import com.lagradost.cloudstream3.utils.DataStoreHelper.removeLastWatched import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultWatchState import com.lagradost.cloudstream3.utils.Event -import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.HOMEPAGE_API +import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showOptionSelectStringRes import com.lagradost.cloudstream3.utils.SubtitleHelper.getFlagFromIso import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe @@ -455,8 +454,10 @@ class HomeFragment : Fragment() { homeViewModel.loadStoredData(list) } - private fun loadHomePage(successful: Boolean = true) { - val apiName = context?.getKey(HOMEPAGE_API) + private fun loadHomePage(successful: Boolean = false) { + val apiName = context?.getKey(USER_SELECTED_HOMEPAGE_API) + + println("LOAD HOMEPAGE $successful $apiName ${homeViewModel.apiName.value}") if (homeViewModel.apiName.value != apiName || apiName == null) { //println("Caught home: " + homeViewModel.apiName.value + " at " + apiName) homeViewModel.loadAndCancel(apiName) @@ -512,7 +513,7 @@ class HomeFragment : Fragment() { observe(homeViewModel.apiName) { apiName -> currentApiName = apiName - setKey(HOMEPAGE_API, apiName) + // setKey(USER_SELECTED_HOMEPAGE_API, apiName) home_api_fab?.text = apiName home_provider_name?.text = apiName try { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt index 7ae0af79..15dd2fc2 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt @@ -31,7 +31,7 @@ import com.lagradost.cloudstream3.utils.DataStoreHelper.getBookmarkedData import com.lagradost.cloudstream3.utils.DataStoreHelper.getLastWatched import com.lagradost.cloudstream3.utils.DataStoreHelper.getResultWatchState import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos -import com.lagradost.cloudstream3.utils.HOMEPAGE_API +import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API import com.lagradost.cloudstream3.utils.VideoDownloadHelper import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -227,7 +227,8 @@ class HomeViewModel : ViewModel() { expandable.clear() data.value.forEach { home -> home?.items?.forEach { list -> - val filteredList = context?.filterHomePageListByFilmQuality(list) ?: list + val filteredList = + context?.filterHomePageListByFilmQuality(list) ?: list expandable[list.name] = ExpandableHomepageList(filteredList, 1, home.hasNext) } @@ -244,7 +245,9 @@ class HomeViewModel : ViewModel() { .toList() if (currentList.isNotEmpty()) { - val randomItems = context?.filterSearchResultByFilmQuality(currentList.shuffled()) ?: currentList.shuffled() + val randomItems = + context?.filterSearchResultByFilmQuality(currentList.shuffled()) + ?: currentList.shuffled() _randomItems.postValue(randomItems) } @@ -266,18 +269,22 @@ class HomeViewModel : ViewModel() { fun loadAndCancel(preferredApiName: String?) = viewModelScope.launch { val api = getApiFromNameNull(preferredApiName) - if (preferredApiName == noneApi.name) + if (preferredApiName == noneApi.name){ + setKey(USER_SELECTED_HOMEPAGE_API, noneApi.name) loadAndCancel(noneApi) + } else if (preferredApiName == randomApi.name || api == null) { val validAPIs = context?.filterProviderByPreferredMedia() if (validAPIs.isNullOrEmpty()) { + // Do not set USER_SELECTED_HOMEPAGE_API when there is no plugins loaded loadAndCancel(noneApi) } else { val apiRandom = validAPIs.random() loadAndCancel(apiRandom) - setKey(HOMEPAGE_API, apiRandom.name) + setKey(USER_SELECTED_HOMEPAGE_API, apiRandom.name) } } else { + setKey(USER_SELECTED_HOMEPAGE_API, api.name) loadAndCancel(api) } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsLang.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsLang.kt index fd5be423..f011bd40 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsLang.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsLang.kt @@ -16,7 +16,7 @@ import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.ui.APIRepository import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setUpToolbar -import com.lagradost.cloudstream3.utils.HOMEPAGE_API +import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showDialog import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showMultiDialog @@ -116,7 +116,7 @@ class SettingsLang : PreferenceFragmentCompat() { .putInt(getString(R.string.prefer_media_type_key), prefValues[it]) .apply() - removeKey(HOMEPAGE_API) + removeKey(USER_SELECTED_HOMEPAGE_API) // (context ?: AcraApplication.context)?.let { ctx -> app.initClient(ctx) } } return@setOnPreferenceClickListener true diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentMedia.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentMedia.kt index cd0c76f5..8d152886 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentMedia.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentMedia.kt @@ -11,7 +11,7 @@ import androidx.navigation.fragment.findNavController import androidx.preference.PreferenceManager import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.utils.DataStore.removeKey -import com.lagradost.cloudstream3.utils.HOMEPAGE_API +import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar import kotlinx.android.synthetic.main.fragment_setup_media.* @@ -52,7 +52,7 @@ class SetupFragmentMedia : Fragment() { .apply() // Regenerate set homepage - removeKey(HOMEPAGE_API) + removeKey(USER_SELECTED_HOMEPAGE_API) } next_btt?.setOnClickListener { diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/AppUtils.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/AppUtils.kt index 190940b5..7102d52a 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/AppUtils.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/AppUtils.kt @@ -2,6 +2,7 @@ package com.lagradost.cloudstream3.utils import android.annotation.SuppressLint import android.app.Activity +import android.app.Activity.RESULT_CANCELED import android.content.ContentValues import android.content.Context import android.content.Intent @@ -21,6 +22,7 @@ import android.provider.MediaStore import android.text.Spanned import android.util.Log import android.widget.Toast +import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.RequiresApi import androidx.annotation.WorkerThread import androidx.appcompat.app.AppCompatActivity @@ -41,13 +43,11 @@ 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.* import com.lagradost.cloudstream3.CommonActivity.showToast import com.lagradost.cloudstream3.MainActivity.Companion.afterRepositoryLoadedEvent -import com.lagradost.cloudstream3.R -import com.lagradost.cloudstream3.SearchResponse -import com.lagradost.cloudstream3.isMovieType -import com.lagradost.cloudstream3.mapper import com.lagradost.cloudstream3.mvvm.logError +import com.lagradost.cloudstream3.mvvm.normalSafeApiCall import com.lagradost.cloudstream3.plugins.RepositoryManager import com.lagradost.cloudstream3.ui.WebviewFragment import com.lagradost.cloudstream3.ui.result.ResultFragment @@ -239,6 +239,7 @@ object AppUtils { ) } } + fun Activity.loadRepository(url: String) { ioSafe { val repo = RepositoryManager.parseRepository(url) ?: return@ioSafe @@ -259,6 +260,18 @@ object AppUtils { } } + private fun Context.hasWebView(): Boolean { + return this.packageManager.hasSystemFeature("android.software.webview") + } + + private fun openWebView(fragment: Fragment?, url: String) { + if (fragment?.context?.hasWebView() == true) + normalSafeApiCall { + fragment + .findNavController() + .navigate(R.id.navigation_webview, WebviewFragment.newInstance(url)) + } + } /** * If fallbackWebview is true and a fragment is supplied then it will open a webview with the url if the browser fails. @@ -266,23 +279,34 @@ object AppUtils { fun Context.openBrowser( url: String, fallbackWebview: Boolean = false, - fragment: Fragment? = null + fragment: Fragment? = null, ) { try { val intent = Intent(Intent.ACTION_VIEW) intent.data = Uri.parse(url) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) - ContextCompat.startActivity(this, intent, null) + + // activityResultRegistry is used to fall back to webview if a browser is missing + // On older versions the startActivity just crashes, but on newer android versions + // You need to check the result to make sure it failed + val activityResultRegistry = fragment?.activity?.activityResultRegistry + if (activityResultRegistry != null) { + activityResultRegistry.register( + url, + ActivityResultContracts.StartActivityForResult() + ) { result -> + if (result.resultCode == RESULT_CANCELED && fallbackWebview) { + openWebView(fragment, url) + } + }.launch(intent) + } else { + ContextCompat.startActivity(this, intent, null) + } + } catch (e: Exception) { logError(e) if (fallbackWebview) { - try { - fragment - ?.findNavController() - ?.navigate(R.id.navigation_webview, WebviewFragment.newInstance(url)) - } catch (e: Exception) { - logError(e) - } + openWebView(fragment, url) } } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/DataStore.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/DataStore.kt index ade1fc38..e1cedd39 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/DataStore.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/DataStore.kt @@ -13,7 +13,7 @@ const val DOWNLOAD_HEADER_CACHE = "download_header_cache" //const val WATCH_HEADER_CACHE = "watch_header_cache" const val DOWNLOAD_EPISODE_CACHE = "download_episode_cache" const val VIDEO_PLAYER_BRIGHTNESS = "video_player_alpha_key" -const val HOMEPAGE_API = "home_api_used" +const val USER_SELECTED_HOMEPAGE_API = "home_api_used" const val USER_PROVIDER_API = "user_custom_sites" const val PREFERENCES_NAME = "rebuild_preference" diff --git a/app/src/main/res/layout/fragment_extensions.xml b/app/src/main/res/layout/fragment_extensions.xml index 8dd029be..d02ddc15 100644 --- a/app/src/main/res/layout/fragment_extensions.xml +++ b/app/src/main/res/layout/fragment_extensions.xml @@ -163,7 +163,7 @@ + tools:src="@drawable/ic_baseline_add_24" + android:focusable="true" /> \ No newline at end of file