This commit is contained in:
LagradOst 2021-08-12 02:04:58 +02:00
parent 5e619c18cc
commit 2839d59a28
11 changed files with 174 additions and 169 deletions

View file

@ -13,8 +13,8 @@ android {
applicationId "com.lagradost.cloudstream3"
minSdkVersion 21
targetSdkVersion 30
versionCode 12
versionName "1.2.1"
versionCode 13
versionName "1.2.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

View file

@ -1,87 +0,0 @@
package com.lagradost.cloudstream3
import com.lagradost.cloudstream3.APIHolder.apis
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.mvvm.safeApiCall
class AllProvider : MainAPI() {
override val name: String
get() = "All Sources"
var providersActive = HashSet<String>()
override fun quickSearch(query: String): ArrayList<SearchResponse>? {
val list = apis.filter { a ->
a.name != this.name && (providersActive.size == 0 || providersActive.contains(a.name))
}.filter { a -> a.hasQuickSearch }.pmap { a ->
normalSafeApiCall {
a.quickSearch(query)
}
}
var maxCount = 0
var providerCount = 0
for (res in list) {
if (res != null) {
if (res.size > maxCount) {
maxCount = res.size
}
providerCount++
}
}
println("PROV: " + providerCount + "|" + maxCount)
if (providerCount == 0) return null
if (maxCount == 0) return ArrayList()
val result = ArrayList<SearchResponse>()
for (i in 0..maxCount) {
for (res in list) {
if (res != null) {
if (i < res.size) {
result.add(res[i])
}
}
}
}
return result
}
override fun search(query: String): ArrayList<SearchResponse>? {
val list = apis.filter { a ->
a.name != this.name && (providersActive.size == 0 || providersActive.contains(a.name))
}.pmap { a ->
normalSafeApiCall {
a.search(query)
}
}
var maxCount = 0
var providerCount = 0
for (res in list) {
if (res != null) {
if (res.size > maxCount) {
maxCount = res.size
}
providerCount++
}
}
if (providerCount == 0) return null
if (maxCount == 0) return ArrayList()
val result = ArrayList<SearchResponse>()
for (i in 0..maxCount) {
for (res in list) {
if (res != null) {
if (i < res.size) {
result.add(res[i])
}
}
}
}
return result
}
}

View file

@ -25,8 +25,6 @@ object APIHolder {
val unixTime: Long
get() = System.currentTimeMillis() / 1000L
val allApi = AllProvider()
private const val defProvider = 0
val apis = arrayListOf(

View file

@ -7,8 +7,13 @@ import com.lagradost.cloudstream3.mvvm.safeApiCall
import com.lagradost.cloudstream3.utils.ExtractorLink
class APIRepository(val api: MainAPI) {
companion object {
var providersActive = HashSet<String>()
}
val name: String get() = api.name
val mainUrl: String get() = api.mainUrl
val hasQuickSearch: Boolean get() = api.hasQuickSearch
suspend fun load(url: String): Resource<LoadResponse> {
return safeApiCall {

View file

@ -1,6 +1,8 @@
package com.lagradost.cloudstream3.ui.home
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.net.Uri
@ -45,6 +47,50 @@ import kotlinx.android.synthetic.main.fragment_home.*
const val HOME_BOOKMARK_VALUE = "home_bookmarked_last"
class HomeFragment : Fragment() {
companion object {
val configEvent = Event<Int>()
var currentSpan = 1
fun Activity.loadHomepageList(item: HomePageList) {
val context = this
val bottomSheetDialogBuilder = BottomSheetDialog(context)
bottomSheetDialogBuilder.setContentView(R.layout.home_episodes_expanded)
val title = bottomSheetDialogBuilder.findViewById<TextView>(R.id.home_expanded_text)!!
title.text = item.name
val recycle = bottomSheetDialogBuilder.findViewById<AutofitRecyclerView>(R.id.home_expanded_recycler)!!
val titleHolder = bottomSheetDialogBuilder.findViewById<FrameLayout>(R.id.home_expanded_drag_down)!!
titleHolder.setOnClickListener {
bottomSheetDialogBuilder.dismiss()
}
// Span settings
recycle.spanCount = currentSpan
recycle.adapter = SearchAdapter(item.list, recycle) { callback ->
handleSearchClickCallback(this, callback)
if (callback.action == SEARCH_ACTION_LOAD) {
bottomSheetDialogBuilder.dismiss()
}
}
val spanListener = { span: Int ->
recycle.spanCount = span
(recycle.adapter as SearchAdapter).notifyDataSetChanged()
}
configEvent += spanListener
bottomSheetDialogBuilder.setOnDismissListener {
configEvent -= spanListener
}
(recycle.adapter as SearchAdapter).notifyDataSetChanged()
bottomSheetDialogBuilder.show()
}
}
private lateinit var homeViewModel: HomeViewModel
override fun onCreateView(
@ -58,8 +104,6 @@ class HomeFragment : Fragment() {
return inflater.inflate(R.layout.fragment_home, container, false)
}
private val configEvent = Event<Int>()
private var currentSpan = 1
private var currentHomePage: HomePageResponse? = null
var currentMainIndex = 0
var currentMainList: ArrayList<SearchResponse> = ArrayList()
@ -254,48 +298,11 @@ class HomeFragment : Fragment() {
}
}
fun loadHomepageList(item: HomePageList) {
val bottomSheetDialogBuilder = BottomSheetDialog(view.context)
bottomSheetDialogBuilder.setContentView(R.layout.home_episodes_expanded)
val title = bottomSheetDialogBuilder.findViewById<TextView>(R.id.home_expanded_text)!!
title.text = item.name
val recycle = bottomSheetDialogBuilder.findViewById<AutofitRecyclerView>(R.id.home_expanded_recycler)!!
val titleHolder = bottomSheetDialogBuilder.findViewById<FrameLayout>(R.id.home_expanded_drag_down)!!
titleHolder.setOnClickListener {
bottomSheetDialogBuilder.dismiss()
}
// Span settings
recycle.spanCount = currentSpan
recycle.adapter = SearchAdapter(item.list, recycle) { callback ->
handleSearchClickCallback(activity, callback)
if (callback.action == SEARCH_ACTION_LOAD) {
bottomSheetDialogBuilder.dismiss()
}
}
val spanListener = { span: Int ->
recycle.spanCount = span
(recycle.adapter as SearchAdapter).notifyDataSetChanged()
}
configEvent += spanListener
bottomSheetDialogBuilder.setOnDismissListener {
configEvent -= spanListener
}
(recycle.adapter as SearchAdapter).notifyDataSetChanged()
bottomSheetDialogBuilder.show()
}
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> = ParentItemAdapter(listOf(), { callback ->
handleSearchClickCallback(activity, callback)
}, { item ->
loadHomepageList(item)
activity?.loadHomepageList(item)
})
observe(homeViewModel.availableWatchStatusTypes) { availableWatchStatusTypes ->
@ -319,7 +326,7 @@ class HomeFragment : Fragment() {
home_bookmarked_child_recyclerview?.adapter?.notifyDataSetChanged()
home_bookmarked_child_more_info.setOnClickListener {
loadHomepageList(
activity?.loadHomepageList(
HomePageList(
home_bookmarked_parent_item_title?.text?.toString() ?: getString(R.string.error_bookmarks_text),
bookmarks

View file

@ -14,16 +14,20 @@ import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.lagradost.cloudstream3.APIHolder.allApi
import com.lagradost.cloudstream3.APIHolder.apis
import com.lagradost.cloudstream3.APIHolder.getApiSettings
import com.lagradost.cloudstream3.HomePageList
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact
import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.mvvm.observe
import com.lagradost.cloudstream3.ui.subtitles.SubtitlesFragment
import com.lagradost.cloudstream3.ui.APIRepository.Companion.providersActive
import com.lagradost.cloudstream3.ui.home.HomeFragment
import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.loadHomepageList
import com.lagradost.cloudstream3.ui.home.ParentItemAdapter
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
import kotlinx.android.synthetic.main.fragment_search.*
@ -49,11 +53,14 @@ class SearchFragment : Fragment() {
val spanCountPortrait = if (compactView) 1 else 3
val orientation = resources.configuration.orientation
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
cardSpace.spanCount = spanCountLandscape
val currentSpan = if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
spanCountLandscape
} else {
cardSpace.spanCount = spanCountPortrait
spanCountPortrait
}
cardSpace.spanCount = currentSpan
HomeFragment.currentSpan = currentSpan
HomeFragment.configEvent.invoke(currentSpan)
}
override fun onConfigurationChanged(newConfig: Configuration) {
@ -113,7 +120,7 @@ class SearchFragment : Fragment() {
apiNames.filter { a -> apiNamesSettingLocal.contains(a) }.toSet()
)
edit.apply()
allApi.providersActive = apiNamesSettingLocal
providersActive = apiNamesSettingLocal
}
}
builder.setTitle("Search Providers")
@ -138,9 +145,11 @@ class SearchFragment : Fragment() {
when (it) {
is Resource.Success -> {
it.value.let { data ->
if (data != null) {
(cardSpace?.adapter as SearchAdapter?)?.cardList = data.filterNotNull()
cardSpace?.adapter?.notifyDataSetChanged()
if (data.isNotEmpty()) {
(cardSpace?.adapter as SearchAdapter?)?.apply {
cardList = data.toList()
notifyDataSetChanged()
}
}
}
searchExitIcon.alpha = 1f
@ -157,8 +166,18 @@ class SearchFragment : Fragment() {
}
}
}
observe(searchViewModel.currentSearch) { list ->
(search_master_recycler?.adapter as ParentItemAdapter?)?.apply {
items = list.map {
HomePageList(it.apiName, if (it.data is Resource.Success) it.data.value else ArrayList())
}
notifyDataSetChanged()
}
}
activity?.let {
allApi.providersActive = it.getApiSettings()
providersActive = it.getApiSettings()
}
main_search.setOnQueryTextFocusChangeListener { searchView, b ->
@ -173,6 +192,22 @@ class SearchFragment : Fragment() {
}
}
main_search.onActionViewExpanded()
val masterAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder> = ParentItemAdapter(listOf(), { callback ->
SearchHelper.handleSearchClickCallback(activity, callback)
}, { item ->
activity?.loadHomepageList(item)
})
search_master_recycler.adapter = masterAdapter
search_master_recycler.layoutManager = GridLayoutManager(context, 1)
val settingsManager = PreferenceManager.getDefaultSharedPreferences(context)
val isAdvancedSearch = settingsManager.getBoolean("advanced_search", true)
search_master_recycler.visibility = if(isAdvancedSearch) View.VISIBLE else View.GONE
cardSpace.visibility = if(!isAdvancedSearch) View.VISIBLE else View.GONE
// SubtitlesFragment.push(activity)
//searchViewModel.search("iron man")
//(activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro")

View file

@ -4,18 +4,27 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.lagradost.cloudstream3.APIHolder.allApi
import com.lagradost.cloudstream3.APIHolder.apis
import com.lagradost.cloudstream3.SearchResponse
import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.mvvm.safeApiCall
import com.lagradost.cloudstream3.ui.APIRepository
import com.lagradost.cloudstream3.ui.APIRepository.Companion.providersActive
import kotlinx.coroutines.launch
data class OnGoingSearch(
val apiName: String,
val data: Resource<ArrayList<SearchResponse>>
)
class SearchViewModel : ViewModel() {
private val _searchResponse: MutableLiveData<Resource<ArrayList<SearchResponse>>> = MutableLiveData()
val searchResponse: LiveData<Resource<ArrayList<SearchResponse>>> get() = _searchResponse
private val _currentSearch: MutableLiveData<ArrayList<OnGoingSearch>> = MutableLiveData()
val currentSearch: LiveData<ArrayList<OnGoingSearch>> get() = _currentSearch
var searchCounter = 0
private val repo = APIRepository(allApi)
private val repos = apis.map { APIRepository(it) }
private fun clearSearch() {
_searchResponse.postValue(Resource.Success(ArrayList()))
@ -23,29 +32,50 @@ class SearchViewModel : ViewModel() {
fun search(query: String) = viewModelScope.launch {
searchCounter++
if(query.length <= 1) {
if (query.length <= 1) {
clearSearch()
return@launch
}
val localSearchCounter = searchCounter
_searchResponse.postValue(Resource.Loading())
val data = repo.search(query)
if(localSearchCounter != searchCounter) return@launch
_searchResponse.postValue(data)
val currentList = ArrayList<OnGoingSearch>()
_currentSearch.postValue(ArrayList())
repos.filter { a ->
(providersActive.size == 0 || providersActive.contains(a.name))
}.map { a ->
currentList.add(OnGoingSearch(a.name, a.search(query)))
if (localSearchCounter == searchCounter) {
_currentSearch.postValue(currentList)
}
}
_currentSearch.postValue(currentList)
if (localSearchCounter != searchCounter) return@launch
val list = ArrayList<SearchResponse>()
val nestedList = currentList.map { it.data }.filterIsInstance<Resource.Success<ArrayList<SearchResponse>>>().map { it.value }
// I do it this way to move the relevant search results to the top
var index = 0
while (true) {
var added = 0
for (sublist in nestedList) {
if(sublist.size > index) {
list.add(sublist[index])
added++
}
}
if(added == 0) break
index++
}
_searchResponse.postValue(Resource.Success(list))
}
fun quickSearch(query: String) = viewModelScope.launch {
searchCounter++
if(query.length <= 1) {
clearSearch()
return@launch
}
val localSearchCounter = searchCounter
_searchResponse.postValue(Resource.Loading())
val data = repo.quickSearch(query)
if(localSearchCounter != searchCounter) return@launch
_searchResponse.postValue(data)
return@launch
}
}

View file

@ -1,8 +1,8 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="vector"
android:width="850dp"
android:height="850dp"
android:width="24dp"
android:height="24dp"
android:viewportWidth="850"
android:viewportHeight="850">
<path

View file

@ -73,7 +73,11 @@
android:id="@+id/cardSpace"
tools:listitem="@layout/search_result_grid"
android:orientation="vertical"
>
</com.lagradost.cloudstream3.ui.AutofitRecyclerView>
/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/search_master_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/homepage_parent"
/>
</LinearLayout>

View file

@ -23,9 +23,9 @@
<color name="white">#FFF</color>
<color name="dubColor">#3d50fa</color> <!--3b65f5 f18c82 8294F1-->
<color name="dubColorBg">#4D3B65F5</color>
<color name="dubColorBg">#803B65F5</color>
<color name="subColor">#F54A3B</color> <!--F53B66 FA3D79-->
<color name="subColorBg">#4DF53B66</color>
<color name="subColorBg">#80F53B66</color>
<color name="typeColor">#F54A3B</color>
<color name="typeColorBg">#4DF54A3B</color>

View file

@ -58,6 +58,19 @@
/>
</PreferenceCategory>
<PreferenceCategory
android:key="search"
android:title="Search"
app:isPreferenceVisible="true"
>
<SwitchPreference
android:icon="@drawable/search_icon"
app:key="advanced_search"
android:title="Advanced Search"
android:summary="Gives you the search results separated by provider"
app:defaultValue="true"
/>
</PreferenceCategory>
<PreferenceCategory
android:key="info"