Added intent to start searching

This commit is contained in:
Blatzar 2022-11-13 01:40:49 +01:00
parent 9a93b375f3
commit 2b29e8078f
5 changed files with 72 additions and 10 deletions

View file

@ -110,6 +110,17 @@
<data android:scheme="cloudstreamrepo" /> <data android:scheme="cloudstreamrepo" />
</intent-filter> </intent-filter>
<!-- Allow searching with intents: cloudstreamsearch://Your%20Name -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="cloudstreamsearch" />
</intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />

View file

@ -16,11 +16,9 @@ import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.navigation.NavController import androidx.navigation.*
import androidx.navigation.NavDestination
import androidx.navigation.NavDestination.Companion.hierarchy import androidx.navigation.NavDestination.Companion.hierarchy
import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavOptions
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
@ -44,6 +42,7 @@ import com.lagradost.cloudstream3.CommonActivity.onUserLeaveHint
import com.lagradost.cloudstream3.CommonActivity.showToast import com.lagradost.cloudstream3.CommonActivity.showToast
import com.lagradost.cloudstream3.CommonActivity.updateLocale import com.lagradost.cloudstream3.CommonActivity.updateLocale
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.network.initClient import com.lagradost.cloudstream3.network.initClient
import com.lagradost.cloudstream3.plugins.PluginManager import com.lagradost.cloudstream3.plugins.PluginManager
import com.lagradost.cloudstream3.plugins.PluginManager.loadSinglePlugin import com.lagradost.cloudstream3.plugins.PluginManager.loadSinglePlugin
@ -52,9 +51,11 @@ import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.OAuth2A
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.accountManagers import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.accountManagers
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appString import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appString
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringRepo import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringRepo
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringSearch
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.inAppAuths import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.inAppAuths
import com.lagradost.cloudstream3.ui.APIRepository import com.lagradost.cloudstream3.ui.APIRepository
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO
import com.lagradost.cloudstream3.ui.search.SearchFragment
import com.lagradost.cloudstream3.ui.search.SearchResultBuilder import com.lagradost.cloudstream3.ui.search.SearchResultBuilder
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isEmulatorSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isEmulatorSettings
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
@ -88,11 +89,9 @@ import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.fragment_result_swipe.* import kotlinx.android.synthetic.main.fragment_result_swipe.*
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import okhttp3.ConnectionSpec
import okhttp3.OkHttpClient
import okhttp3.internal.applyConnectionSpec
import java.io.File import java.io.File
import java.net.URI import java.net.URI
import java.net.URLDecoder
import java.nio.charset.Charset import java.nio.charset.Charset
import kotlin.reflect.KClass import kotlin.reflect.KClass
@ -147,7 +146,7 @@ val VLC = ResultResume(
val MPV = ResultResume( val MPV = ResultResume(
MPV_PACKAGE, MPV_PACKAGE,
//"is.xyz.mpv.MPVActivity.result", // resume not working :pensive: //"is.xyz.mpv.MPVActivity.result", // resume not working :pensive:
position = "position", position = "position",
duration = "duration", duration = "duration",
) )
@ -188,6 +187,15 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
companion object { companion object {
const val TAG = "MAINACT" const val TAG = "MAINACT"
/**
* Setting this will automatically enter the query in the search
* next time the search fragment is opened.
* This variable will clear itself after one use. Null does nothing.
*
* This is a very bad solution but I was unable to find a better one.
**/
private var nextSearchQuery: String? = null
/** /**
* Fires every time a new batch of plugins have been loaded, no guarantee about how often this is run and on which thread * Fires every time a new batch of plugins have been loaded, no guarantee about how often this is run and on which thread
* */ * */
@ -206,6 +214,9 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
isWebview: Boolean isWebview: Boolean
): Boolean = ): Boolean =
with(activity) { with(activity) {
// Invalid URIs can crash
fun safeURI(uri: String) = normalSafeApiCall { URI(uri) }
if (str != null && this != null) { if (str != null && this != null) {
if (str.startsWith("https://cs.repo")) { if (str.startsWith("https://cs.repo")) {
val realUrl = "https://" + str.substringAfter("?") val realUrl = "https://" + str.substringAfter("?")
@ -241,10 +252,14 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
return true return true
} }
} }
} else if (URI(str).scheme == appStringRepo) { } else if (safeURI(str)?.scheme == appStringRepo) {
val url = str.replaceFirst(appStringRepo, "https") val url = str.replaceFirst(appStringRepo, "https")
loadRepository(url) loadRepository(url)
return true return true
} else if (safeURI(str)?.scheme == appStringSearch) {
nextSearchQuery =
URLDecoder.decode(str.substringAfter("$appStringSearch://"), "UTF-8")
nav_view.selectedItemId = R.id.navigation_search
} else if (!isWebview) { } else if (!isWebview) {
if (str.startsWith(DOWNLOAD_NAVIGATE_TO)) { if (str.startsWith(DOWNLOAD_NAVIGATE_TO)) {
this.navigate(R.id.navigation_downloads) this.navigate(R.id.navigation_downloads)
@ -619,6 +634,17 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
val navHostFragment = val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController val navController = navHostFragment.navController
navController.addOnDestinationChangedListener { _: NavController, navDestination: NavDestination, bundle: Bundle? ->
// Intercept search and add a query
if (navDestination.matchDestination(R.id.navigation_search) && !nextSearchQuery.isNullOrBlank()) {
bundle?.apply {
this.putString(SearchFragment.SEARCH_QUERY, nextSearchQuery)
nextSearchQuery = null
}
}
}
//val navController = findNavController(R.id.nav_host_fragment) //val navController = findNavController(R.id.nav_host_fragment)
/*navOptions = NavOptions.Builder() /*navOptions = NavOptions.Builder()

View file

@ -43,6 +43,9 @@ abstract class AccountManager(private val defIndex: Int) : AuthAPI {
const val appString = "cloudstreamapp" const val appString = "cloudstreamapp"
const val appStringRepo = "cloudstreamrepo" const val appStringRepo = "cloudstreamrepo"
// Instantly start the search given a query
const val appStringSearch = "cloudstreamsearch"
val unixTime: Long val unixTime: Long
get() = System.currentTimeMillis() / 1000L get() = System.currentTimeMillis() / 1000L
val unixTimeMs: Long val unixTimeMs: Long

View file

@ -73,6 +73,14 @@ class SearchFragment : Fragment() {
} }
} }
} }
const val SEARCH_QUERY = "search_query"
fun newInstance(query: String): Bundle {
return Bundle().apply {
putString(SEARCH_QUERY, query)
}
}
} }
private val searchViewModel: SearchViewModel by activityViewModels() private val searchViewModel: SearchViewModel by activityViewModels()
@ -132,7 +140,8 @@ class SearchFragment : Fragment() {
val default = enumValues<TvType>().sorted().filter { it != TvType.NSFW } val default = enumValues<TvType>().sorted().filter { it != TvType.NSFW }
.map { it.ordinal.toString() }.toSet() .map { it.ordinal.toString() }.toSet()
val preferredTypes = (PreferenceManager.getDefaultSharedPreferences(ctx) val preferredTypes = (PreferenceManager.getDefaultSharedPreferences(ctx)
.getStringSet(this.getString(R.string.prefer_media_type_key), default)?.ifEmpty { default } ?: default) .getStringSet(this.getString(R.string.prefer_media_type_key), default)
?.ifEmpty { default } ?: default)
.mapNotNull { it.toIntOrNull() ?: return@mapNotNull null } .mapNotNull { it.toIntOrNull() ?: return@mapNotNull null }
val settings = ctx.getApiSettings() val settings = ctx.getApiSettings()
@ -487,6 +496,14 @@ class SearchFragment : Fragment() {
search_master_recycler?.adapter = masterAdapter search_master_recycler?.adapter = masterAdapter
search_master_recycler?.layoutManager = GridLayoutManager(context, 1) search_master_recycler?.layoutManager = GridLayoutManager(context, 1)
// Automatically search the specified query, this allows the app search to launch from intent
arguments?.getString(SEARCH_QUERY)?.let { query ->
if (query.isBlank()) return@let
main_search?.setQuery(query, true)
// Clear the query as to not make it request the same query every time the page is opened
arguments?.putString(SEARCH_QUERY, null)
}
// SubtitlesFragment.push(activity) // SubtitlesFragment.push(activity)
//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")

View file

@ -274,7 +274,12 @@
app:exitAnim="@anim/exit_anim" app:exitAnim="@anim/exit_anim"
app:popEnterAnim="@anim/enter_anim" app:popEnterAnim="@anim/enter_anim"
app:popExitAnim="@anim/exit_anim" app:popExitAnim="@anim/exit_anim"
tools:layout="@layout/fragment_search" /> tools:layout="@layout/fragment_search">
<argument
android:name="search_query"
android:defaultValue=""
app:argType="string" />
</fragment>
<fragment <fragment
android:id="@+id/navigation_downloads" android:id="@+id/navigation_downloads"