new quicksearch

This commit is contained in:
LagradOst 2022-04-30 03:13:50 +02:00
parent 3b4915444a
commit 30fddb0360
6 changed files with 147 additions and 61 deletions

View file

@ -103,11 +103,13 @@ open class WcoStream : ExtractorApi() {
).apmap { serverurl -> ).apmap { serverurl ->
val testurl = app.get(serverurl, headers = mapOf("Referer" to url)).text val testurl = app.get(serverurl, headers = mapOf("Referer" to url)).text
if (testurl.contains("EXTM3")) { if (testurl.contains("EXTM3")) {
val quality = if (serverurl.contains("H4")) "1080p" val quality = when {
else if (serverurl.contains("H3")) "720p" serverurl.contains("H4") -> "1080p"
else if (serverurl.contains("H2")) "480p" serverurl.contains("H3") -> "720p"
else if (serverurl.contains("H1")) "360p" serverurl.contains("H2") -> "480p"
else "Auto" serverurl.contains("H1") -> "360p"
else -> "Auto"
}
sources.add( sources.add(
ExtractorLink( ExtractorLink(
"VidStream", "VidStream",

View file

@ -474,7 +474,7 @@ class HomeFragment : Fragment() {
home_search?.setOnQueryTextListener(object : SearchView.OnQueryTextListener { home_search?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean { override fun onQueryTextSubmit(query: String): Boolean {
QuickSearchFragment.pushSearch(activity, query) QuickSearchFragment.pushSearch(activity, query, currentApiName?.let { arrayOf(it) })
return true return true
} }

View file

@ -1,6 +1,8 @@
package com.lagradost.cloudstream3.ui.quicksearch package com.lagradost.cloudstream3.ui.quicksearch
import android.app.Activity import android.app.Activity
import android.content.Context
import android.content.res.Configuration
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -8,16 +10,19 @@ import android.view.ViewGroup
import android.view.WindowManager import android.view.WindowManager
import android.widget.ImageView import android.widget.ImageView
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.lagradost.cloudstream3.APIHolder.filterProviderByPreferredMedia import com.lagradost.cloudstream3.APIHolder.filterProviderByPreferredMedia
import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
import com.lagradost.cloudstream3.HomePageList import com.lagradost.cloudstream3.HomePageList
import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.mvvm.Resource import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.mvvm.observe import com.lagradost.cloudstream3.mvvm.observe
import com.lagradost.cloudstream3.ui.home.HomeFragment
import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.loadHomepageList import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.loadHomepageList
import com.lagradost.cloudstream3.ui.home.ParentItemAdapter import com.lagradost.cloudstream3.ui.home.ParentItemAdapter
import com.lagradost.cloudstream3.ui.search.SearchAdapter import com.lagradost.cloudstream3.ui.search.SearchAdapter
@ -27,19 +32,29 @@ import com.lagradost.cloudstream3.ui.search.SearchHelper
import com.lagradost.cloudstream3.ui.search.SearchViewModel import com.lagradost.cloudstream3.ui.search.SearchViewModel
import com.lagradost.cloudstream3.utils.UIHelper import com.lagradost.cloudstream3.utils.UIHelper
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
import com.lagradost.cloudstream3.utils.UIHelper.getSpanCount
import com.lagradost.cloudstream3.utils.UIHelper.navigate import com.lagradost.cloudstream3.utils.UIHelper.navigate
import com.lagradost.cloudstream3.utils.UIHelper.popCurrentPage import com.lagradost.cloudstream3.utils.UIHelper.popCurrentPage
import kotlinx.android.synthetic.main.fragment_search.*
import kotlinx.android.synthetic.main.quick_search.* import kotlinx.android.synthetic.main.quick_search.*
import java.util.concurrent.locks.ReentrantLock import java.util.concurrent.locks.ReentrantLock
class QuickSearchFragment : Fragment() { class QuickSearchFragment : Fragment() {
companion object { companion object {
fun pushSearch(activity: Activity?, autoSearch: String? = null) { const val AUTOSEARCH_KEY = "autosearch"
const val PROVIDER_KEY = "providers"
fun pushSearch(
activity: Activity?,
autoSearch: String? = null,
providers: Array<String>? = null
) {
activity.navigate(R.id.global_to_navigation_quick_search, Bundle().apply { activity.navigate(R.id.global_to_navigation_quick_search, Bundle().apply {
providers?.let {
putStringArray(PROVIDER_KEY, it)
}
autoSearch?.let { autoSearch?.let {
putString( putString(
"autosearch", AUTOSEARCH_KEY,
it.trim() it.trim()
.removeSuffix("(DUB)") .removeSuffix("(DUB)")
.removeSuffix("(SUB)") .removeSuffix("(SUB)")
@ -53,7 +68,8 @@ class QuickSearchFragment : Fragment() {
var clickCallback: ((SearchClickCallback) -> Unit)? = null var clickCallback: ((SearchClickCallback) -> Unit)? = null
} }
private val searchViewModel: SearchViewModel by activityViewModels() private var providers: Set<String>? = null
private lateinit var searchViewModel: SearchViewModel
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
@ -63,6 +79,7 @@ class QuickSearchFragment : Fragment() {
activity?.window?.setSoftInputMode( activity?.window?.setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
) )
searchViewModel = ViewModelProvider(this)[SearchViewModel::class.java]
return inflater.inflate(R.layout.quick_search, container, false) return inflater.inflate(R.layout.quick_search, container, false)
} }
@ -72,9 +89,75 @@ class QuickSearchFragment : Fragment() {
clickCallback = null clickCallback = null
} }
fun search(context: Context?, query: String, isQuickSearch: Boolean): Boolean {
(providers ?: context?.filterProviderByPreferredMedia(hasHomePageIsRequired = false)
?.map { it.name }?.toSet())?.let { active ->
searchViewModel.searchAndCancel(
query = query,
ignoreSettings = false,
providersActive = active,
isQuickSearch = isQuickSearch
)
return true
}
return false
}
private fun fixGrid() {
activity?.getSpanCount()?.let {
HomeFragment.currentSpan = it
}
quick_search_autofit_results.spanCount = HomeFragment.currentSpan
HomeFragment.currentSpan = HomeFragment.currentSpan
HomeFragment.configEvent.invoke(HomeFragment.currentSpan)
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
fixGrid()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
context?.fixPaddingStatusbar(quick_search_root) context?.fixPaddingStatusbar(quick_search_root)
fixGrid()
arguments?.getStringArray(PROVIDER_KEY)?.let {
providers = it.toSet()
}
val isSingleProvider = providers?.size == 1
val isSingleProviderQuickSearch = if (isSingleProvider) {
getApiFromNameNull(providers?.first())?.hasQuickSearch ?: false
} else false
if (isSingleProvider) {
quick_search_autofit_results.adapter = activity?.let {
SearchAdapter(
ArrayList(),
quick_search_autofit_results,
) { callback ->
SearchHelper.handleSearchClickCallback(activity, callback)
}
}
} else {
quick_search_master_recycler?.adapter =
ParentItemAdapter(mutableListOf(), { callback ->
SearchHelper.handleSearchClickCallback(activity, callback)
//when (callback.action) {
//SEARCH_ACTION_LOAD -> {
// clickCallback?.invoke(callback)
//}
// else -> SearchHelper.handleSearchClickCallback(activity, callback)
//}
}, { item ->
activity?.loadHomepageList(item)
})
quick_search_master_recycler?.layoutManager = GridLayoutManager(context, 1)
}
quick_search_autofit_results?.isVisible = isSingleProvider
quick_search_master_recycler?.isGone = isSingleProvider
val listLock = ReentrantLock() val listLock = ReentrantLock()
observe(searchViewModel.currentSearch) { list -> observe(searchViewModel.currentSearch) { list ->
@ -97,19 +180,6 @@ class QuickSearchFragment : Fragment() {
} }
} }
val masterAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder> =
ParentItemAdapter(mutableListOf(), { callback ->
SearchHelper.handleSearchClickCallback(activity, callback)
//when (callback.action) {
//SEARCH_ACTION_LOAD -> {
// clickCallback?.invoke(callback)
//}
// else -> SearchHelper.handleSearchClickCallback(activity, callback)
//}
}, { item ->
activity?.loadHomepageList(item)
})
val searchExitIcon = val searchExitIcon =
quick_search?.findViewById<ImageView>(androidx.appcompat.R.id.search_close_btn) quick_search?.findViewById<ImageView>(androidx.appcompat.R.id.search_close_btn)
@ -119,25 +189,17 @@ class QuickSearchFragment : Fragment() {
//searchMagIcon?.scaleX = 0.65f //searchMagIcon?.scaleX = 0.65f
//searchMagIcon?.scaleY = 0.65f //searchMagIcon?.scaleY = 0.65f
quick_search?.setOnQueryTextListener(object : SearchView.OnQueryTextListener { quick_search?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean { override fun onQueryTextSubmit(query: String): Boolean {
context?.filterProviderByPreferredMedia(hasHomePageIsRequired = false) if (search(context, query, false))
?.map { it.name }?.toSet()?.let { active -> UIHelper.hideKeyboard(quick_search)
searchViewModel.searchAndCancel(
query = query,
ignoreSettings = false,
providersActive = active
)
quick_search?.let {
UIHelper.hideKeyboard(it)
}
}
return true return true
} }
override fun onQueryTextChange(newText: String): Boolean { override fun onQueryTextChange(newText: String): Boolean {
//searchViewModel.quickSearch(newText) if (isSingleProviderQuickSearch)
search(context, newText, true)
return true return true
} }
}) })
@ -147,9 +209,10 @@ class QuickSearchFragment : Fragment() {
when (it) { when (it) {
is Resource.Success -> { is Resource.Success -> {
it.value.let { data -> it.value.let { data ->
if (data.isNotEmpty()) { println("DATA: $data")
(search_autofit_results?.adapter as? SearchAdapter?)?.updateList(data) (quick_search_autofit_results?.adapter as? SearchAdapter?)?.updateList(
} data
)
} }
searchExitIcon?.alpha = 1f searchExitIcon?.alpha = 1f
quick_search_loading_bar?.alpha = 0f quick_search_loading_bar?.alpha = 0f
@ -166,8 +229,6 @@ class QuickSearchFragment : Fragment() {
} }
} }
quick_search_master_recycler?.adapter = masterAdapter
quick_search_master_recycler?.layoutManager = GridLayoutManager(context, 1)
//quick_search.setOnQueryTextFocusChangeListener { _, b -> //quick_search.setOnQueryTextFocusChangeListener { _, b ->
// if (b) { // if (b) {
@ -180,9 +241,9 @@ class QuickSearchFragment : Fragment() {
activity?.popCurrentPage() activity?.popCurrentPage()
} }
arguments?.getString("autosearch")?.let { arguments?.getString(AUTOSEARCH_KEY)?.let {
quick_search?.setQuery(it, true) quick_search?.setQuery(it, true)
arguments?.remove("autosearch") arguments?.remove(AUTOSEARCH_KEY)
} }
} }
} }

View file

@ -47,10 +47,11 @@ class SearchViewModel : ViewModel() {
fun searchAndCancel( fun searchAndCancel(
query: String, query: String,
providersActive: Set<String> = setOf(), providersActive: Set<String> = setOf(),
ignoreSettings: Boolean = false ignoreSettings: Boolean = false,
isQuickSearch: Boolean = false,
) { ) {
onGoingSearch?.cancel() onGoingSearch?.cancel()
onGoingSearch = search(query, providersActive, ignoreSettings) onGoingSearch = search(query, providersActive, ignoreSettings, isQuickSearch)
} }
fun updateHistory() = viewModelScope.launch { fun updateHistory() = viewModelScope.launch {
@ -65,7 +66,8 @@ class SearchViewModel : ViewModel() {
private fun search( private fun search(
query: String, query: String,
providersActive: Set<String>, providersActive: Set<String>,
ignoreSettings: Boolean = false ignoreSettings: Boolean = false,
isQuickSearch: Boolean = false,
) = ) =
viewModelScope.launch { viewModelScope.launch {
if (query.length <= 1) { if (query.length <= 1) {
@ -73,17 +75,19 @@ class SearchViewModel : ViewModel() {
return@launch return@launch
} }
val key = query.hashCode().toString() if (!isQuickSearch) {
setKey( val key = query.hashCode().toString()
SEARCH_HISTORY_KEY, setKey(
key, SEARCH_HISTORY_KEY,
SearchHistoryItem( key,
searchedAt = System.currentTimeMillis(), SearchHistoryItem(
searchText = query, searchedAt = System.currentTimeMillis(),
type = emptyList(), // TODO implement tv type searchText = query,
key = key, type = emptyList(), // TODO implement tv type
key = key,
)
) )
) }
_searchResponse.postValue(Resource.Loading()) _searchResponse.postValue(Resource.Loading())
@ -93,9 +97,9 @@ class SearchViewModel : ViewModel() {
withContext(Dispatchers.IO) { // This interrupts UI otherwise withContext(Dispatchers.IO) { // This interrupts UI otherwise
repos.filter { a -> repos.filter { a ->
ignoreSettings || (providersActive.isEmpty() || providersActive.contains(a.name)) (ignoreSettings || (providersActive.isEmpty() || providersActive.contains(a.name))) && (!isQuickSearch || a.hasQuickSearch)
}.apmap { a -> // Parallel }.apmap { a -> // Parallel
val search = a.search(query) val search = if (isQuickSearch) a.quickSearch(query) else a.search(query)
currentList.add(OnGoingSearch(a.name, search)) currentList.add(OnGoingSearch(a.name, search))
_currentSearch.postValue(currentList) _currentSearch.postValue(currentList)
} }

View file

@ -384,7 +384,9 @@ object UIHelper {
} }
} }
fun hideKeyboard(view: View) { fun hideKeyboard(view: View?) {
if(view == null) return
val inputMethodManager = val inputMethodManager =
view.context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager? view.context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager?
inputMethodManager?.hideSoftInputFromWindow(view.windowToken, 0) inputMethodManager?.hideSoftInputFromWindow(view.windowToken, 0)

View file

@ -83,4 +83,21 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:listitem="@layout/homepage_parent" /> tools:listitem="@layout/homepage_parent" />
<com.lagradost.cloudstream3.ui.AutofitRecyclerView
android:visibility="gone"
android:nextFocusLeft="@id/nav_rail_view"
android:descendantFocusability="afterDescendants"
android:background="?attr/primaryBlackBackground"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingStart="8dp"
android:paddingTop="5dp"
app:spanCount="3"
android:paddingEnd="8dp"
android:id="@+id/quick_search_autofit_results"
tools:listitem="@layout/search_result_grid"
android:orientation="vertical" />
</LinearLayout> </LinearLayout>