forked from recloudstream/cloudstream
Add list switcher
This commit is contained in:
parent
67a1c447ae
commit
2a2a0a26e7
4 changed files with 71 additions and 36 deletions
|
@ -1,12 +1,9 @@
|
|||
package com.lagradost.cloudstream3.syncproviders.providers
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper
|
||||
import com.fasterxml.jackson.module.kotlin.KotlinModule
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.APIHolder.capitalize
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKeys
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.openBrowser
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
|
@ -141,7 +138,8 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
this.name,
|
||||
recMedia.id?.toString() ?: return@mapNotNull null,
|
||||
getUrlFromId(recMedia.id),
|
||||
recMedia.coverImage?.large ?: recMedia.coverImage?.medium
|
||||
recMedia.coverImage?.extraLarge ?: recMedia.coverImage?.large
|
||||
?: recMedia.coverImage?.medium
|
||||
)
|
||||
},
|
||||
trailers = when (season.trailer?.site?.lowercase()?.trim()) {
|
||||
|
@ -220,7 +218,7 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
romaji
|
||||
}
|
||||
idMal
|
||||
coverImage { medium large }
|
||||
coverImage { medium large extraLarge }
|
||||
averageScore
|
||||
}
|
||||
}
|
||||
|
@ -233,7 +231,7 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
format
|
||||
id
|
||||
idMal
|
||||
coverImage { medium large }
|
||||
coverImage { medium large extraLarge }
|
||||
averageScore
|
||||
title {
|
||||
english
|
||||
|
@ -569,7 +567,8 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
|
||||
data class CoverImage(
|
||||
@JsonProperty("medium") val medium: String?,
|
||||
@JsonProperty("large") val large: String?
|
||||
@JsonProperty("large") val large: String?,
|
||||
@JsonProperty("extraLarge") val extraLarge: String?
|
||||
)
|
||||
|
||||
data class Media(
|
||||
|
@ -600,16 +599,17 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
fun toLibraryItem(listName: String?): LibraryItem? {
|
||||
return LibraryItem(
|
||||
// English title first
|
||||
this.media.title.english ?: this.media.title.romaji ?: this.media.synonyms.firstOrNull()
|
||||
this.media.title.english ?: this.media.title.romaji
|
||||
?: this.media.synonyms.firstOrNull()
|
||||
?: "",
|
||||
"https://anilist.co/anime/${this.media.id}/",
|
||||
listName ?: return null,
|
||||
listName?.lowercase()?.capitalize() ?: return null,
|
||||
this.progress,
|
||||
this.media.episodes,
|
||||
this.score,
|
||||
"AniList",
|
||||
TvType.Anime,
|
||||
this.media.coverImage.large ?: this.media.coverImage.medium,
|
||||
this.media.coverImage.extraLarge ?: this.media.coverImage.large ?: this.media.coverImage.medium,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
|
@ -630,44 +630,44 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
@JsonProperty("MediaListCollection") val MediaListCollection: MediaListCollection
|
||||
)
|
||||
|
||||
fun getAnilistListCached(): Array<Lists>? {
|
||||
private fun getAniListListCached(): Array<Lists>? {
|
||||
return getKey(ANILIST_CACHED_LIST) as? Array<Lists>
|
||||
}
|
||||
|
||||
suspend fun getAnilistAnimeListSmart(): Array<Lists>? {
|
||||
private suspend fun getAniListAnimeListSmart(): Array<Lists>? {
|
||||
if (getAuth() == null) return null
|
||||
|
||||
if (checkToken()) return null
|
||||
return if (getKey(ANILIST_SHOULD_UPDATE_LIST, true) == true) {
|
||||
val list = getFullAnilistList()?.data?.MediaListCollection?.lists?.toTypedArray()
|
||||
val list = getFullAniListList()?.data?.MediaListCollection?.lists?.toTypedArray()
|
||||
if (list != null) {
|
||||
setKey(ANILIST_CACHED_LIST, list)
|
||||
setKey(ANILIST_SHOULD_UPDATE_LIST, false)
|
||||
}
|
||||
list
|
||||
} else {
|
||||
getAnilistListCached()
|
||||
getAniListListCached()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPersonalLibrary(): List<LibraryItem>? {
|
||||
return getAnilistAnimeListSmart()?.map { it.entries.mapNotNull { entry -> entry.toLibraryItem(entry.status ?: it.status) } }?.flatten()
|
||||
return getAniListAnimeListSmart()?.map {
|
||||
it.entries.mapNotNull { entry ->
|
||||
entry.toLibraryItem(
|
||||
entry.status ?: it.status
|
||||
)
|
||||
}
|
||||
}?.flatten()
|
||||
}
|
||||
|
||||
private suspend fun getFullAnilistList(): FullAnilistList? {
|
||||
var userID: Int? = null
|
||||
private suspend fun getFullAniListList(): FullAnilistList? {
|
||||
/** WARNING ASSUMES ONE USER! **/
|
||||
getKeys(ANILIST_USER_KEY)?.forEach { key ->
|
||||
getKey<AniListUser>(key, null)?.let {
|
||||
userID = it.id
|
||||
}
|
||||
}
|
||||
|
||||
val fixedUserID = userID ?: return null
|
||||
val userID = getKey<AniListUser>(accountId, ANILIST_USER_KEY)?.id ?: return null
|
||||
val mediaType = "ANIME"
|
||||
|
||||
val query = """
|
||||
query (${'$'}userID: Int = $fixedUserID, ${'$'}MEDIA: MediaType = $mediaType) {
|
||||
query (${'$'}userID: Int = $userID, ${'$'}MEDIA: MediaType = $mediaType) {
|
||||
MediaListCollection (userId: ${'$'}userID, type: ${'$'}MEDIA) {
|
||||
lists {
|
||||
status
|
||||
|
@ -694,7 +694,7 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
english
|
||||
romaji
|
||||
}
|
||||
coverImage { medium }
|
||||
coverImage { extraLarge large medium }
|
||||
synonyms
|
||||
nextAiringEpisode {
|
||||
timeUntilAiring
|
||||
|
@ -706,7 +706,9 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
}
|
||||
}
|
||||
"""
|
||||
val text = postApi(query)
|
||||
val text = postApi(query).also {
|
||||
println("REPONSE $it")
|
||||
}
|
||||
return text?.toKotlinObject()
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,22 @@ class LibraryFragment : Fragment() {
|
|||
|
||||
libraryViewModel.loadPages()
|
||||
|
||||
list_selector?.setOnClickListener {
|
||||
val items = libraryViewModel.availableApiNames
|
||||
val currentItem = libraryViewModel.currentApiName.value
|
||||
|
||||
activity?.showBottomDialog(
|
||||
items,
|
||||
items.indexOf(currentItem),
|
||||
"Select library",
|
||||
false,
|
||||
{}
|
||||
) {
|
||||
val selectedItem = items.getOrNull(it) ?: return@showBottomDialog
|
||||
libraryViewModel.switchList(selectedItem)
|
||||
}
|
||||
}
|
||||
|
||||
viewpager?.setPageTransformer(LibraryScrollTransformer())
|
||||
viewpager?.adapter =
|
||||
viewpager.adapter ?: ViewpagerAdapter(emptyList(), { isScrollingDown: Boolean ->
|
||||
|
|
|
@ -8,7 +8,6 @@ import com.lagradost.cloudstream3.R
|
|||
import com.lagradost.cloudstream3.mvvm.Resource
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.SyncApis
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||
import me.xdrop.fuzzywuzzy.FuzzySearch
|
||||
|
||||
enum class ListSorting(@StringRes val stringRes: Int) {
|
||||
Query(R.string.none),
|
||||
|
@ -27,8 +26,10 @@ class LibraryViewModel : ViewModel() {
|
|||
private val _currentApiName: MutableLiveData<String> = MutableLiveData("")
|
||||
val currentApiName: LiveData<String> = _currentApiName
|
||||
|
||||
private val listApis = SyncApis.filter { it.hasAccount() }
|
||||
private var currentApi = listApis.firstOrNull()
|
||||
private val availableSyncApis = SyncApis.filter { it.hasAccount() }
|
||||
private var currentSyncApi = availableSyncApis.firstOrNull()
|
||||
|
||||
val availableApiNames: List<String> = availableSyncApis.map { it.name }
|
||||
|
||||
val sortingMethods = listOf(
|
||||
ListSorting.RatingHigh,
|
||||
|
@ -42,8 +43,10 @@ class LibraryViewModel : ViewModel() {
|
|||
var currentSortingMethod: ListSorting = sortingMethods.first()
|
||||
private set
|
||||
|
||||
fun switchList() {
|
||||
currentApi = listApis[(listApis.indexOf(currentApi) + 1) % listApis.size]
|
||||
fun switchList(name: String) {
|
||||
currentSyncApi = availableSyncApis[availableApiNames.indexOf(name)]
|
||||
_currentApiName.postValue(currentSyncApi?.name)
|
||||
|
||||
loadPages()
|
||||
}
|
||||
|
||||
|
@ -58,7 +61,7 @@ class LibraryViewModel : ViewModel() {
|
|||
|
||||
fun loadPages() {
|
||||
ioSafe {
|
||||
currentApi?.let { repo ->
|
||||
currentSyncApi?.let { repo ->
|
||||
val list = (repo.getPersonalLibrary() as? Resource.Success)?.value
|
||||
val pages = (list ?: emptyList()).groupBy { it.listName }.map {
|
||||
Page(
|
||||
|
|
|
@ -34,8 +34,6 @@
|
|||
android:nextFocusLeft="@id/nav_rail_view"
|
||||
|
||||
android:nextFocusRight="@id/search_filter"
|
||||
android:nextFocusUp="@id/nav_rail_view"
|
||||
android:nextFocusDown="@id/search_autofit_results"
|
||||
android:paddingStart="-10dp"
|
||||
app:iconifiedByDefault="false"
|
||||
app:queryBackground="@color/transparent"
|
||||
|
@ -44,6 +42,22 @@
|
|||
tools:ignore="RtlSymmetry">
|
||||
|
||||
</androidx.appcompat.widget.SearchView>
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/list_selector"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
|
||||
android:layout_margin="10dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/change_providers_img_des"
|
||||
android:nextFocusLeft="@id/main_search"
|
||||
android:nextFocusRight="@id/main_search"
|
||||
android:src="@drawable/ic_baseline_filter_list_24"
|
||||
app:tint="?attr/textColor" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
@ -76,7 +90,7 @@
|
|||
style="@style/ExtendedFloatingActionButton"
|
||||
android:text="Sort"
|
||||
android:textColor="?attr/textColor"
|
||||
app:icon="@drawable/ic_baseline_filter_list_24"
|
||||
app:icon="@drawable/ic_baseline_sort_24"
|
||||
tools:ignore="ContentDescription" />
|
||||
</FrameLayout>
|
||||
|
||||
|
|
Loading…
Reference in a new issue