Fix searching race condition with loading plugins

This commit is contained in:
Blatzar 2022-08-18 00:26:50 +02:00
parent 4832421bd2
commit e9e4298a7a
2 changed files with 91 additions and 60 deletions

View file

@ -22,11 +22,11 @@ import com.google.android.material.button.MaterialButton
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.APIHolder.filterProviderByPreferredMedia import com.lagradost.cloudstream3.APIHolder.filterProviderByPreferredMedia
import com.lagradost.cloudstream3.APIHolder.filterSearchResultByFilmQuality import com.lagradost.cloudstream3.APIHolder.filterSearchResultByFilmQuality
import com.lagradost.cloudstream3.APIHolder.getApiFromName
import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings
import com.lagradost.cloudstream3.APIHolder.getApiSettings import com.lagradost.cloudstream3.APIHolder.getApiSettings
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
import com.lagradost.cloudstream3.MainActivity.Companion.afterPluginsLoadedEvent
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
@ -36,6 +36,7 @@ import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.currentSpan
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.settings.SettingsFragment.Companion.isTrueTvSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
import com.lagradost.cloudstream3.utils.Coroutines.main
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.SubtitleHelper import com.lagradost.cloudstream3.utils.SubtitleHelper
@ -97,6 +98,16 @@ class SearchFragment : Fragment() {
super.onDestroyView() super.onDestroyView()
} }
override fun onResume() {
super.onResume()
afterPluginsLoadedEvent += ::reloadRepos
}
override fun onStop() {
super.onStop()
afterPluginsLoadedEvent -= ::reloadRepos
}
var selectedSearchTypes = mutableListOf<TvType>() var selectedSearchTypes = mutableListOf<TvType>()
var selectedApis = mutableSetOf<String>() var selectedApis = mutableSetOf<String>()
@ -116,11 +127,73 @@ class SearchFragment : Fragment() {
} }
} }
// Null if defined as a variable
// This needs to be run after view created
private fun getPairList(): List<Pair<MaterialButton?, List<TvType>>> {
return HomeFragment.getPairList(
search_select_anime,
search_select_cartoons,
search_select_tv_series,
search_select_documentaries,
search_select_movies,
search_select_asian,
search_select_livestreams,
search_select_nsfw,
search_select_others
)
}
private fun reloadRepos(success: Boolean = false) = main {
val pairList = getPairList()
searchViewModel.reloadRepos()
context?.filterProviderByPreferredMedia()?.let { validAPIs ->
for ((button, validTypes) in pairList) {
val isValid =
validAPIs.any { api -> validTypes.any { api.supportedTypes.contains(it) } }
button?.isVisible = isValid
if (isValid) {
fun buttonContains(): Boolean {
return selectedSearchTypes.any { validTypes.contains(it) }
}
button?.isSelected = buttonContains()
button?.setOnClickListener {
val last = selectedSearchTypes.toSet()
selectedSearchTypes.clear()
selectedSearchTypes.addAll(validTypes)
for ((otherButton, _) in pairList) {
otherButton?.isSelected = false
}
it?.context?.setKey(SEARCH_PREF_TAGS, selectedSearchTypes)
it?.isSelected = true
if (last != selectedSearchTypes.toSet()) // if you click the same button again the it does nothing
search(main_search?.query?.toString())
}
button?.setOnLongClickListener {
if (!buttonContains()) {
it?.isSelected = true
selectedSearchTypes.addAll(validTypes)
} else {
it?.isSelected = false
selectedSearchTypes.removeAll(validTypes)
}
it?.context?.setKey(SEARCH_PREF_TAGS, selectedSearchTypes)
search(main_search?.query?.toString())
return@setOnLongClickListener true
}
}
}
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
context?.fixPaddingStatusbar(searchRoot) context?.fixPaddingStatusbar(searchRoot)
fixGrid() fixGrid()
reloadRepos()
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder>? = activity?.let { val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder>? = activity?.let {
SearchAdapter( SearchAdapter(
@ -155,6 +228,7 @@ class SearchFragment : Fragment() {
var currentValidApis = listOf<MainAPI>() var currentValidApis = listOf<MainAPI>()
val currentSelectedApis = if (selectedApis.isEmpty()) validAPIs.map { it.name } val currentSelectedApis = if (selectedApis.isEmpty()) validAPIs.map { it.name }
.toMutableSet() else selectedApis .toMutableSet() else selectedApis
val builder = val builder =
BottomSheetDialog(ctx) BottomSheetDialog(ctx)
@ -169,7 +243,8 @@ class SearchFragment : Fragment() {
val docs = dialog.findViewById<MaterialButton>(R.id.home_select_documentaries) val docs = dialog.findViewById<MaterialButton>(R.id.home_select_documentaries)
val movies = dialog.findViewById<MaterialButton>(R.id.home_select_movies) val movies = dialog.findViewById<MaterialButton>(R.id.home_select_movies)
val asian = dialog.findViewById<MaterialButton>(R.id.home_select_asian) val asian = dialog.findViewById<MaterialButton>(R.id.home_select_asian)
val livestream = dialog.findViewById<MaterialButton>(R.id.home_select_livestreams) val livestream =
dialog.findViewById<MaterialButton>(R.id.home_select_livestreams)
val nsfw = dialog.findViewById<MaterialButton>(R.id.home_select_nsfw) val nsfw = dialog.findViewById<MaterialButton>(R.id.home_select_nsfw)
val other = dialog.findViewById<MaterialButton>(R.id.home_select_others) val other = dialog.findViewById<MaterialButton>(R.id.home_select_others)
val cancelBtt = dialog.findViewById<MaterialButton>(R.id.cancel_btt) val cancelBtt = dialog.findViewById<MaterialButton>(R.id.cancel_btt)
@ -221,7 +296,7 @@ class SearchFragment : Fragment() {
listView?.choiceMode = AbsListView.CHOICE_MODE_MULTIPLE listView?.choiceMode = AbsListView.CHOICE_MODE_MULTIPLE
listView?.setOnItemClickListener { _, _, i, _ -> listView?.setOnItemClickListener { _, _, i, _ ->
if (!currentValidApis.isNullOrEmpty()) { if (currentValidApis.isNotEmpty()) {
val api = currentValidApis[i].name val api = currentValidApis[i].name
if (currentSelectedApis.contains(api)) { if (currentSelectedApis.contains(api)) {
listView.setItemChecked(i, false) listView.setItemChecked(i, false)
@ -295,18 +370,6 @@ class SearchFragment : Fragment() {
} }
} }
val pairList = HomeFragment.getPairList(
search_select_anime,
search_select_cartoons,
search_select_tv_series,
search_select_documentaries,
search_select_movies,
search_select_asian,
search_select_livestreams,
search_select_nsfw,
search_select_others
)
val settingsManager = context?.let { PreferenceManager.getDefaultSharedPreferences(it) } val settingsManager = context?.let { PreferenceManager.getDefaultSharedPreferences(it) }
val isAdvancedSearch = settingsManager?.getBoolean("advanced_search", true) ?: true val isAdvancedSearch = settingsManager?.getBoolean("advanced_search", true) ?: true
@ -315,6 +378,7 @@ class SearchFragment : Fragment() {
?.toMutableList() ?.toMutableList()
?: mutableListOf(TvType.Movie, TvType.TvSeries) ?: mutableListOf(TvType.Movie, TvType.TvSeries)
val pairList = getPairList()
fun updateSelectedList(list: MutableList<TvType>) { fun updateSelectedList(list: MutableList<TvType>) {
selectedSearchTypes = list selectedSearchTypes = list
for ((button, validTypes) in pairList) { for ((button, validTypes) in pairList) {
@ -322,46 +386,6 @@ class SearchFragment : Fragment() {
} }
} }
context?.filterProviderByPreferredMedia()?.let { validAPIs ->
for ((button, validTypes) in pairList) {
val isValid =
validAPIs.any { api -> validTypes.any { api.supportedTypes.contains(it) } }
button?.isVisible = isValid
if (isValid) {
fun buttonContains(): Boolean {
return selectedSearchTypes.any { validTypes.contains(it) }
}
button?.isSelected = buttonContains()
button?.setOnClickListener {
val last = selectedSearchTypes.toSet()
selectedSearchTypes.clear()
selectedSearchTypes.addAll(validTypes)
for ((otherButton, _) in pairList) {
otherButton?.isSelected = false
}
it?.context?.setKey(SEARCH_PREF_TAGS, selectedSearchTypes)
it?.isSelected = true
if (last != selectedSearchTypes.toSet()) // if you click the same button again the it does nothing
search(main_search?.query?.toString())
}
button?.setOnLongClickListener {
if (!buttonContains()) {
it?.isSelected = true
selectedSearchTypes.addAll(validTypes)
} else {
it?.isSelected = false
selectedSearchTypes.removeAll(validTypes)
}
it?.context?.setKey(SEARCH_PREF_TAGS, selectedSearchTypes)
search(main_search?.query?.toString())
return@setOnLongClickListener true
}
}
}
}
if (context?.isTrueTvSettings() == true) { if (context?.isTrueTvSettings() == true) {
search_filter.isFocusable = true search_filter.isFocusable = true
search_filter.isFocusableInTouchMode = true search_filter.isFocusableInTouchMode = true
@ -431,8 +455,10 @@ class SearchFragment : Fragment() {
listLock.lock() listLock.lock()
(search_master_recycler?.adapter as ParentItemAdapter?)?.apply { (search_master_recycler?.adapter as ParentItemAdapter?)?.apply {
val newItems = list.map { ongoing -> val newItems = list.map { ongoing ->
val dataList = if (ongoing.data is Resource.Success) ongoing.data.value else ArrayList() val dataList =
val dataListFiltered = context?.filterSearchResultByFilmQuality(dataList) ?: dataList if (ongoing.data is Resource.Success) ongoing.data.value else ArrayList()
val dataListFiltered =
context?.filterSearchResultByFilmQuality(dataList) ?: dataList
val ongoingList = HomePageList( val ongoingList = HomePageList(
ongoing.apiName, ongoing.apiName,
dataListFiltered dataListFiltered

View file

@ -36,7 +36,7 @@ class SearchViewModel : ViewModel() {
private val _currentHistory: MutableLiveData<List<SearchHistoryItem>> = MutableLiveData() private val _currentHistory: MutableLiveData<List<SearchHistoryItem>> = MutableLiveData()
val currentHistory: LiveData<List<SearchHistoryItem>> get() = _currentHistory val currentHistory: LiveData<List<SearchHistoryItem>> get() = _currentHistory
private val repos = apis.map { APIRepository(it) } private var repos = apis.map { APIRepository(it) }
fun clearSearch() { fun clearSearch() {
_searchResponse.postValue(Resource.Success(ArrayList())) _searchResponse.postValue(Resource.Success(ArrayList()))
@ -45,6 +45,11 @@ class SearchViewModel : ViewModel() {
private var currentSearchIndex = 0 private var currentSearchIndex = 0
private var onGoingSearch: Job? = null private var onGoingSearch: Job? = null
fun reloadRepos() {
repos = apis.map { APIRepository(it) }
}
fun searchAndCancel( fun searchAndCancel(
query: String, query: String,
providersActive: Set<String> = setOf(), providersActive: Set<String> = setOf(),