lib longhold

This commit is contained in:
LagradOst 2023-12-21 00:07:39 +01:00
parent 1356a954f3
commit e886fde8b8
12 changed files with 279 additions and 71 deletions

View file

@ -60,7 +60,7 @@ android {
targetSdk = 33 /* Android 14 is Fu*ked
^ https://developer.android.com/about/versions/14/behavior-changes-14#safer-dynamic-code-loading*/
versionCode = 63
versionName = "4.3.0"
versionName = "4.3.1"
resValue("string", "app_version", "${defaultConfig.versionName}${versionNameSuffix ?: ""}")
resValue("string", "commit_hash", "git rev-parse --short HEAD".execute() ?: "")

View file

@ -92,7 +92,9 @@ import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStri
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringResumeWatching
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringSearch
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.inAppAuths
import com.lagradost.cloudstream3.syncproviders.SyncAPI
import com.lagradost.cloudstream3.ui.APIRepository
import com.lagradost.cloudstream3.ui.SyncWatchType
import com.lagradost.cloudstream3.ui.WatchType
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO
import com.lagradost.cloudstream3.ui.home.HomeViewModel
@ -102,6 +104,7 @@ import com.lagradost.cloudstream3.ui.player.LinkGenerator
import com.lagradost.cloudstream3.ui.result.LinearListLayout
import com.lagradost.cloudstream3.ui.result.ResultViewModel2
import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST
import com.lagradost.cloudstream3.ui.result.SyncViewModel
import com.lagradost.cloudstream3.ui.result.setImage
import com.lagradost.cloudstream3.ui.result.setText
import com.lagradost.cloudstream3.ui.result.txt
@ -440,13 +443,30 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
}
var lastPopup: SearchResponse? = null
fun loadPopup(result: SearchResponse) {
fun loadPopup(result: SearchResponse, load : Boolean = true) {
lastPopup = result
viewModel.load(
this, result.url, result.apiName, false, if (getApiDubstatusSettings()
.contains(DubStatus.Dubbed)
) DubStatus.Dubbed else DubStatus.Subbed, null
)
val syncName = syncViewModel.syncName(result.apiName)
// based on apiName we decide on if it is a local list or not, this is because
// we want to show a bit of extra UI to sync apis
if (result is SyncAPI.LibraryItem && syncName != null) {
isLocalList = false
syncViewModel.setSync(syncName, result.syncId)
syncViewModel.updateMetaAndUser()
} else {
isLocalList = true
syncViewModel.clear()
}
if (load) {
viewModel.load(
this, result.url, result.apiName, false, if (getApiDubstatusSettings()
.contains(DubStatus.Dubbed)
) DubStatus.Dubbed else DubStatus.Subbed, null
)
}else {
viewModel.loadSmall(this,result)
}
}
override fun onColorSelected(dialogId: Int, color: Int) {
@ -734,10 +754,14 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
}
lateinit var viewModel: ResultViewModel2
lateinit var syncViewModel : SyncViewModel
/** kinda dirty, however it signals that we should use the watch status as sync or not*/
var isLocalList : Boolean = false
override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
viewModel =
ViewModelProvider(this)[ResultViewModel2::class.java]
syncViewModel =
ViewModelProvider(this)[SyncViewModel::class.java]
return super.onCreateView(name, context, attrs)
}
@ -1235,13 +1259,48 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
builder.show().setDefaultFocus()
}
observe(viewModel.watchStatus) { state ->
fun setUserData(status : Resource<SyncAPI.AbstractSyncStatus>?) {
if (isLocalList) return
bottomPreviewBinding?.apply {
when (status) {
is Resource.Success -> {
resultviewPreviewBookmark.isEnabled = true
resultviewPreviewBookmark.setText(status.value.status.stringRes)
resultviewPreviewBookmark.setIconResource(status.value.status.iconRes)
}
is Resource.Failure -> {
resultviewPreviewBookmark.isEnabled = false
resultviewPreviewBookmark.setIconResource(R.drawable.ic_baseline_bookmark_border_24)
resultviewPreviewBookmark.text = status.errorString
}
else -> {
resultviewPreviewBookmark.isEnabled = false
resultviewPreviewBookmark.setIconResource(R.drawable.ic_baseline_bookmark_border_24)
resultviewPreviewBookmark.setText(R.string.loading)
}
}
}
}
fun setWatchStatus(state : WatchType?) {
if (!isLocalList || state == null) return
bottomPreviewBinding?.resultviewPreviewBookmark?.apply {
setIconResource(state.iconRes)
setText(state.stringRes)
}
}
observe(viewModel.watchStatus) { state ->
setWatchStatus(state)
}
observe(syncViewModel.userData) { status ->
setUserData(status)
}
observeNullable(viewModel.page) { resource ->
if (resource == null) {
hidePreviewPopupDialog()
@ -1281,17 +1340,37 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
d.posterImage ?: d.posterBackgroundImage
)
setUserData(syncViewModel.userData.value)
setWatchStatus(viewModel.watchStatus.value)
resultviewPreviewBookmark.setOnClickListener {
//viewModel.updateWatchStatus(WatchType.PLANTOWATCH)
val value = viewModel.watchStatus.value ?: WatchType.NONE
if (isLocalList) {
val value = viewModel.watchStatus.value ?: WatchType.NONE
this@MainActivity.showBottomDialog(
WatchType.values().map { getString(it.stringRes) }.toList(),
value.ordinal,
this@MainActivity.getString(R.string.action_add_to_bookmarks),
showApply = false,
{}) {
viewModel.updateWatchStatus(WatchType.values()[it], this@MainActivity)
this@MainActivity.showBottomDialog(
WatchType.values().map { getString(it.stringRes) }.toList(),
value.ordinal,
this@MainActivity.getString(R.string.action_add_to_bookmarks),
showApply = false,
{}) {
viewModel.updateWatchStatus(
WatchType.values()[it],
this@MainActivity
)
}
} else {
val value = (syncViewModel.userData.value as? Resource.Success)?.value?.status ?: SyncWatchType.NONE
this@MainActivity.showBottomDialog(
SyncWatchType.values().map { getString(it.stringRes) }.toList(),
value.ordinal,
this@MainActivity.getString(R.string.action_add_to_bookmarks),
showApply = false,
{}) {
syncViewModel.setStatus(SyncWatchType.values()[it].internalId)
syncViewModel.publishUserData()
}
}
}

View file

@ -1,6 +1,8 @@
package com.lagradost.cloudstream3.syncproviders
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.ui.SyncWatchType
import com.lagradost.cloudstream3.ui.WatchType
import com.lagradost.cloudstream3.ui.library.ListSorting
import com.lagradost.cloudstream3.ui.result.UiText
import me.xdrop.fuzzywuzzy.FuzzySearch
@ -61,7 +63,7 @@ interface SyncAPI : OAuth2API {
) : SearchResponse
abstract class AbstractSyncStatus {
abstract var status: Int
abstract var status: SyncWatchType
/** 1-10 */
abstract var score: Int?
@ -70,8 +72,9 @@ interface SyncAPI : OAuth2API {
abstract var maxEpisodes: Int?
}
data class SyncStatus(
override var status: Int,
override var status: SyncWatchType,
/** 1-10 */
override var score: Int?,
override var watchedEpisodes: Int?,
@ -166,5 +169,8 @@ interface SyncAPI : OAuth2API {
override var posterHeaders: Map<String, String>?,
override var quality: SearchQuality?,
override var id: Int? = null,
val plot : String? = null,
val rating: Int? = null,
val tags: List<String>? = null,
) : SearchResponse
}

View file

@ -13,6 +13,7 @@ import com.lagradost.cloudstream3.syncproviders.AccountManager
import com.lagradost.cloudstream3.syncproviders.AuthAPI
import com.lagradost.cloudstream3.syncproviders.SyncAPI
import com.lagradost.cloudstream3.syncproviders.SyncIdName
import com.lagradost.cloudstream3.ui.SyncWatchType
import com.lagradost.cloudstream3.ui.library.ListSorting
import com.lagradost.cloudstream3.ui.result.txt
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
@ -165,7 +166,7 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
return SyncAPI.SyncStatus(
score = data.score,
watchedEpisodes = data.progress,
status = data.type?.value ?: return null,
status = SyncWatchType.fromInternalId(data.type?.value ?: return null),
isFavorite = data.isFavourite,
maxEpisodes = data.episodes,
)
@ -174,7 +175,7 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
override suspend fun score(id: String, status: SyncAPI.AbstractSyncStatus): Boolean {
return postDataAboutId(
id.toIntOrNull() ?: return false,
fromIntToAnimeStatus(status.status),
fromIntToAnimeStatus(status.status.internalId),
status.score,
status.watchedEpisodes
).also {
@ -595,7 +596,7 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
//@JsonProperty("source") val source: String,
@JsonProperty("episodes") val episodes: Int,
@JsonProperty("title") val title: Title,
//@JsonProperty("description") val description: String,
@JsonProperty("description") val description: String?,
@JsonProperty("coverImage") val coverImage: CoverImage,
@JsonProperty("synonyms") val synonyms: List<String>,
@JsonProperty("nextAiringEpisode") val nextAiringEpisode: SeasonNextAiringEpisode?,
@ -629,7 +630,8 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
?: this.media.coverImage.medium,
null,
null,
null
null,
plot = this.media.description
)
}
}

View file

@ -16,6 +16,7 @@ import com.lagradost.cloudstream3.syncproviders.AccountManager
import com.lagradost.cloudstream3.syncproviders.AuthAPI
import com.lagradost.cloudstream3.syncproviders.SyncAPI
import com.lagradost.cloudstream3.syncproviders.SyncIdName
import com.lagradost.cloudstream3.ui.SyncWatchType
import com.lagradost.cloudstream3.ui.library.ListSorting
import com.lagradost.cloudstream3.ui.result.txt
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
@ -94,7 +95,7 @@ class MALApi(index: Int) : AccountManager(index), SyncAPI {
override suspend fun score(id: String, status: SyncAPI.AbstractSyncStatus): Boolean {
return setScoreRequest(
id.toIntOrNull() ?: return false,
fromIntToAnimeStatus(status.status),
fromIntToAnimeStatus(status.status.internalId),
status.score,
status.watchedEpisodes
).also {
@ -245,7 +246,7 @@ class MALApi(index: Int) : AccountManager(index), SyncAPI {
getDataAboutMalId(internalId)?.my_list_status //?: throw ErrorLoadingException("No my_list_status")
return SyncAPI.SyncStatus(
score = data?.score,
status = malStatusAsString.indexOf(data?.status),
status = SyncWatchType.fromInternalId(malStatusAsString.indexOf(data?.status)) ,
isFavorite = null,
watchedEpisodes = data?.num_episodes_watched,
)
@ -442,6 +443,7 @@ class MALApi(index: Int) : AccountManager(index), SyncAPI {
this.node.main_picture?.large ?: this.node.main_picture?.medium,
null,
null,
plot = this.node.synopsis,
)
}
}

View file

@ -24,6 +24,7 @@ import com.lagradost.cloudstream3.syncproviders.AccountManager
import com.lagradost.cloudstream3.syncproviders.AuthAPI
import com.lagradost.cloudstream3.syncproviders.SyncAPI
import com.lagradost.cloudstream3.syncproviders.SyncIdName
import com.lagradost.cloudstream3.ui.SyncWatchType
import com.lagradost.cloudstream3.ui.library.ListSorting
import com.lagradost.cloudstream3.ui.result.txt
import com.lagradost.cloudstream3.utils.AppUtils.toJson
@ -671,7 +672,7 @@ class SimklApi(index: Int) : AccountManager(index), SyncAPI {
this.movie.poster?.let { getPosterUrl(it) },
null,
null,
movie.ids.simkl
movie.ids.simkl,
)
}
}
@ -779,7 +780,7 @@ class SimklApi(index: Int) : AccountManager(index), SyncAPI {
}
class SimklSyncStatus(
override var status: Int,
override var status: SyncWatchType,
override var score: Int?,
val oldScore: Int?,
override var watchedEpisodes: Int?,
@ -826,7 +827,7 @@ class SimklApi(index: Int) : AccountManager(index), SyncAPI {
if (foundItem != null) {
return SimklSyncStatus(
status = foundItem.status?.let { SimklListStatusType.fromString(it)?.value }
status = foundItem.status?.let { SyncWatchType.fromInternalId(SimklListStatusType.fromString(it)?.value) }
?: return null,
score = foundItem.user_rating,
watchedEpisodes = foundItem.watched_episodes_count,
@ -838,7 +839,7 @@ class SimklApi(index: Int) : AccountManager(index), SyncAPI {
)
} else {
return SimklSyncStatus(
status = SimklListStatusType.None.value,
status = SyncWatchType.fromInternalId(SimklListStatusType.None.value) ,
score = 0,
watchedEpisodes = 0,
maxEpisodes = if (searchResult.type == "movie") 0 else searchResult.total_episodes,
@ -858,7 +859,7 @@ class SimklApi(index: Int) : AccountManager(index), SyncAPI {
val builder = SimklScoreBuilder.Builder()
.apiUrl(this.mainUrl)
.score(status.score, simklStatus?.oldScore)
.status(status.status, (status as? SimklSyncStatus)?.oldStatus?.let { oldStatus ->
.status(status.status.internalId, (status as? SimklSyncStatus)?.oldStatus?.let { oldStatus ->
SimklListStatusType.values().firstOrNull {
it.originalName == oldStatus
}?.value
@ -871,7 +872,7 @@ class SimklApi(index: Int) : AccountManager(index), SyncAPI {
val episodes = simklStatus?.episodeConstructor?.getEpisodes()
// All episodes if marked as completed
val watchedEpisodes = if (status.status == SimklListStatusType.Completed.value) {
val watchedEpisodes = if (status.status.internalId == SimklListStatusType.Completed.value) {
episodes?.size
} else {
status.watchedEpisodes

View file

@ -12,6 +12,29 @@ enum class WatchType(val internalId: Int, @StringRes val stringRes: Int, @Drawab
PLANTOWATCH(4, R.string.type_plan_to_watch, R.drawable.ic_baseline_bookmark_24),
NONE(5, R.string.type_none, R.drawable.ic_baseline_add_24);
companion object {
fun fromInternalId(id: Int?) = values().find { value -> value.internalId == id } ?: NONE
}
}
enum class SyncWatchType(val internalId: Int, @StringRes val stringRes: Int, @DrawableRes val iconRes: Int) {
/*
-1 -> None
0 -> Watching
1 -> Completed
2 -> OnHold
3 -> Dropped
4 -> PlanToWatch
5 -> ReWatching
*/
NONE(-1, R.string.type_none, R.drawable.ic_baseline_add_24),
WATCHING(0, R.string.type_watching, R.drawable.ic_baseline_bookmark_24),
COMPLETED(1, R.string.type_completed, R.drawable.ic_baseline_bookmark_24),
ONHOLD(2, R.string.type_on_hold, R.drawable.ic_baseline_bookmark_24),
DROPPED(3, R.string.type_dropped, R.drawable.ic_baseline_bookmark_24),
PLANTOWATCH(4, R.string.type_plan_to_watch, R.drawable.ic_baseline_bookmark_24),
REWATCHING(5, R.string.type_plan_to_watch, R.drawable.ic_baseline_bookmark_24);
companion object {
fun fromInternalId(id: Int?) = values().find { value -> value.internalId == id } ?: NONE
}

View file

@ -33,6 +33,7 @@ import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
import com.lagradost.cloudstream3.AcraApplication.Companion.openBrowser
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
import com.lagradost.cloudstream3.CommonActivity
import com.lagradost.cloudstream3.MainActivity
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.databinding.FragmentLibraryBinding
import com.lagradost.cloudstream3.mvvm.Resource
@ -293,11 +294,12 @@ class LibraryFragment : Fragment() {
when (searchClickCallback.action) {
SEARCH_ACTION_SHOW_METADATA -> {
activity?.showPluginSelectionDialog(
(activity as? MainActivity)?.loadPopup(searchClickCallback.card, load = false)
/*activity?.showPluginSelectionDialog(
syncId,
syncName,
searchClickCallback.card.apiName
)
)*/
}
SEARCH_ACTION_LOAD -> {

View file

@ -851,7 +851,7 @@ open class ResultFragmentPhone : FullScreenPlayer() {
val d = status.value
resultSyncRating.value = d.score?.toFloat() ?: 0.0f
resultSyncCheck.setItemChecked(d.status + 1, true)
resultSyncCheck.setItemChecked(d.status.internalId + 1, true)
val watchedEpisodes = d.watchedEpisodes ?: 0
currentSyncProgress = watchedEpisodes

View file

@ -826,16 +826,15 @@ class ResultViewModel2 : ViewModel() {
private val _selectPopup: MutableLiveData<SelectPopup?> = MutableLiveData(null)
val selectPopup: LiveData<SelectPopup?> = _selectPopup
fun updateWatchStatus(
status: WatchType,
context: Context?,
loadResponse: LoadResponse? = null,
statusChangedCallback: ((statusChanged: Boolean) -> Unit)? = null
) {
val response = loadResponse ?: currentResponse ?: return
val currentId = response.getId()
val (response,currentId) = loadResponse?.let { load ->
(load to load.getId())
} ?: ((currentResponse ?: return) to (currentId ?: return))
val currentStatus = getResultWatchState(currentId)
@ -885,13 +884,17 @@ class ResultViewModel2 : ViewModel() {
response.type,
response.posterUrl,
response.year,
response.syncData
response.syncData,
plot = response.plot,
tags = response.tags,
rating = response.rating
)
)
}
if (currentStatus != status) {
MainActivity.bookmarksUpdatedEvent(true)
MainActivity.reloadLibraryEvent(true)
}
_watchStatus.postValue(status)
@ -926,7 +929,7 @@ class ResultViewModel2 : ViewModel() {
val response = currentResponse ?: return
if (response !is EpisodeResponse) return
val currentId = response.getId()
val currentId = currentId ?: return
if (isSubscribed) {
removeSubscribedData(currentId)
@ -969,7 +972,10 @@ class ResultViewModel2 : ViewModel() {
response.type,
response.posterUrl,
response.year,
response.syncData
response.syncData,
plot = response.plot,
rating = response.rating,
tags = response.tags
)
)
@ -994,7 +1000,7 @@ class ResultViewModel2 : ViewModel() {
val isFavorite = _favoriteStatus.value ?: return
val response = currentResponse ?: return
val currentId = response.getId()
val currentId = currentId ?: return
if (isFavorite) {
removeFavoritesData(currentId)
@ -1036,7 +1042,10 @@ class ResultViewModel2 : ViewModel() {
response.type,
response.posterUrl,
response.year,
response.syncData
response.syncData,
plot = response.plot,
rating = response.rating,
tags = response.tags
)
)
@ -1839,10 +1848,10 @@ class ResultViewModel2 : ViewModel() {
this.japName
).filter { it.length > 2 }
.distinct().map {
// this actually would be nice if we improved a bit as 3rd season == season 3 == III ect
// this actually would be nice if we improved a bit as 3rd season == season 3 == III ect
// right now it just removes the dubbed status
it.lowercase().replace(Regex("""\(?[ds]ub(bed)?\)?(\s|$)""") , "").trim()
},
},
TrackerType.getTypes(this.type),
this.year
)
@ -1936,6 +1945,7 @@ class ResultViewModel2 : ViewModel() {
postSuccessful(
value ?: return@launchSafe,
currentId ?: return@launchSafe,
currentRepo ?: return@launchSafe,
updateEpisodes ?: return@launchSafe,
false
@ -2050,9 +2060,9 @@ class ResultViewModel2 : ViewModel() {
}
private fun postFavorites(loadResponse: LoadResponse) {
val id = loadResponse.getId()
val isFavorite = getFavoritesData(id) != null
_favoriteStatus.postValue(isFavorite)
val id = loadResponse.getId()
val isFavorite = getFavoritesData(id) != null
_favoriteStatus.postValue(isFavorite)
}
private fun postEpisodeRange(indexer: EpisodeIndexer?, range: EpisodeRange?) {
@ -2185,26 +2195,25 @@ class ResultViewModel2 : ViewModel() {
private suspend fun postSuccessful(
loadResponse: LoadResponse,
mainId : Int,
apiRepository: APIRepository,
updateEpisodes: Boolean,
updateFillers: Boolean,
) {
currentId = mainId
currentResponse = loadResponse
postPage(loadResponse, apiRepository)
postSubscription(loadResponse)
postFavorites(loadResponse)
_watchStatus.postValue(getResultWatchState(mainId))
if (updateEpisodes)
postEpisodes(loadResponse, updateFillers)
postEpisodes(loadResponse, mainId, updateFillers)
}
private suspend fun postEpisodes(loadResponse: LoadResponse, updateFillers: Boolean) {
private suspend fun postEpisodes(loadResponse: LoadResponse, mainId : Int, updateFillers: Boolean) {
_episodes.postValue(Resource.Loading())
val mainId = loadResponse.getId()
currentId = mainId
_watchStatus.postValue(getResultWatchState(mainId))
if (updateFillers && loadResponse is AnimeLoadResponse) {
updateFillers(loadResponse.name)
}
@ -2561,6 +2570,49 @@ class ResultViewModel2 : ViewModel() {
}
}
data class LoadResponseFromSearch(
override var name: String,
override var url: String,
override var apiName: String,
override var type: TvType,
override var posterUrl: String?,
override var year: Int? = null,
override var plot: String? = null,
override var rating: Int? = null,
override var tags: List<String>? = null,
override var duration: Int? = null,
override var trailers: MutableList<TrailerData> = mutableListOf(),
override var recommendations: List<SearchResponse>? = null,
override var actors: List<ActorData>? = null,
override var comingSoon: Boolean = false,
override var syncData: MutableMap<String, String> = mutableMapOf(),
override var posterHeaders: Map<String, String>? = null,
override var backgroundPosterUrl: String? = null,
override var contentRating: String? = null,
) : LoadResponse
fun loadSmall(activity: Activity?, searchResponse : SearchResponse) = ioSafe {
val url = searchResponse.url
_page.postValue(Resource.Loading(url))
_episodes.postValue(Resource.Loading())
val api = APIHolder.getApiFromNameNull(searchResponse.apiName) ?: APIHolder.getApiFromUrlNull(searchResponse.url) ?: APIRepository.noneApi
val repo = APIRepository(api)
val response = LoadResponseFromSearch(name = searchResponse.name, url = searchResponse.url, apiName = api.name, type = searchResponse.type ?: TvType.Others,
posterUrl = searchResponse.posterUrl).apply {
if (searchResponse is SyncAPI.LibraryItem) {
this.plot = searchResponse.plot
this.rating = searchResponse.personalRating?.times(100) ?: searchResponse.rating
this.tags = searchResponse.tags
}
}
val mainId = searchResponse.id ?: response.getId()
postSuccessful(
loadResponse = response,
mainId = mainId,
apiRepository = repo, updateEpisodes = false, updateFillers = false)
}
fun load(
activity: Activity?,
url: String,
@ -2646,6 +2698,7 @@ class ResultViewModel2 : ViewModel() {
loadTrailers(data.value)
postSuccessful(
data.value,
mainId,
updateEpisodes = true,
updateFillers = showFillers,
apiRepository = repo

View file

@ -10,7 +10,9 @@ import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.SyncApis
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.aniListApi
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.malApi
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.simklApi
import com.lagradost.cloudstream3.syncproviders.SyncAPI
import com.lagradost.cloudstream3.ui.SyncWatchType
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
import com.lagradost.cloudstream3.utils.SyncUtil
import java.util.*
@ -31,15 +33,15 @@ class SyncViewModel : ViewModel() {
private val repos = SyncApis
private val _metaResponse: MutableLiveData<Resource<SyncAPI.SyncResult>> =
MutableLiveData()
private val _metaResponse: MutableLiveData<Resource<SyncAPI.SyncResult>?> =
MutableLiveData(null)
val metadata: LiveData<Resource<SyncAPI.SyncResult>> get() = _metaResponse
val metadata: LiveData<Resource<SyncAPI.SyncResult>?> = _metaResponse
private val _userDataResponse: MutableLiveData<Resource<SyncAPI.AbstractSyncStatus>?> =
MutableLiveData(null)
val userData: LiveData<Resource<SyncAPI.AbstractSyncStatus>?> get() = _userDataResponse
val userData: LiveData<Resource<SyncAPI.AbstractSyncStatus>?> = _userDataResponse
// prefix, id
private val syncs = mutableMapOf<String, String>()
@ -55,7 +57,7 @@ class SyncViewModel : ViewModel() {
MutableLiveData(getMissing())
// pair of name idPrefix isSynced
val synced: LiveData<List<CurrentSynced>> get() = _currentSynced
val synced: LiveData<List<CurrentSynced>> = _currentSynced
private fun getMissing(): List<CurrentSynced> {
return repos.map {
@ -169,7 +171,7 @@ class SyncViewModel : ViewModel() {
if (which < -1 || which > 5) return // validate input
val user = userData.value
if (user is Resource.Success) {
user.value.status = which
user.value.status = SyncWatchType.fromInternalId(which)
_userDataResponse.postValue(Resource.Success(user.value))
}
}
@ -279,7 +281,33 @@ class SyncViewModel : ViewModel() {
setEpisodesDelta(0)
}
fun syncName(syncName: String) : String? {
// fix because of bad old data :pensive:
val realName = when(syncName) {
"MAL" -> malApi.idPrefix
"Simkl" -> simklApi.idPrefix
"AniList" -> aniListApi.idPrefix
else -> syncName
}
return repos.firstOrNull { it.idPrefix == realName }?.idPrefix
}
fun setSync(syncName : String, syncId : String) {
syncs.clear()
syncs[syncName] = syncId
}
fun clear() {
syncs.clear()
_metaResponse.postValue(null)
_currentSynced.postValue(getMissing())
_userDataResponse.postValue(null)
}
fun updateMetaAndUser() {
_userDataResponse.postValue(Resource.Loading())
_metaResponse.postValue(Resource.Loading())
Log.i(TAG, "updateMetaAndUser")
updateMetadata()
updateUserData()

View file

@ -209,7 +209,10 @@ object DataStoreHelper {
@JsonProperty("year") open val year: Int?,
@JsonProperty("syncData") open val syncData: Map<String, String>?,
@JsonProperty("quality") override var quality: SearchQuality?,
@JsonProperty("posterHeaders") override var posterHeaders: Map<String, String>?
@JsonProperty("posterHeaders") override var posterHeaders: Map<String, String>?,
@JsonProperty("plot") open val plot : String? = null,
@JsonProperty("rating") open val rating : Int? = null,
@JsonProperty("tags") open val tags : List<String>? = null,
) : SearchResponse
data class SubscribedData(
@ -225,8 +228,11 @@ object DataStoreHelper {
override val year: Int?,
override val syncData: Map<String, String>? = null,
override var quality: SearchQuality? = null,
override var posterHeaders: Map<String, String>? = null
) : LibrarySearchResponse(id, latestUpdatedTime, name, url, apiName, type, posterUrl, year, syncData, quality, posterHeaders) {
override var posterHeaders: Map<String, String>? = null,
override val plot: String? = null,
override val rating: Int? = null,
override val tags: List<String>? = null,
) : LibrarySearchResponse(id, latestUpdatedTime, name, url, apiName, type, posterUrl, year, syncData, quality, posterHeaders, plot,rating,tags) {
fun toLibraryItem(): SyncAPI.LibraryItem? {
return SyncAPI.LibraryItem(
name,
@ -236,7 +242,7 @@ object DataStoreHelper {
null,
null,
latestUpdatedTime,
apiName, type, posterUrl, posterHeaders, quality, this.id
apiName, type, posterUrl, posterHeaders, quality, this.id, plot = this.plot, rating = this.rating, tags = this.tags
)
}
}
@ -253,8 +259,11 @@ object DataStoreHelper {
override val year: Int?,
override val syncData: Map<String, String>? = null,
override var quality: SearchQuality? = null,
override var posterHeaders: Map<String, String>? = null
) : LibrarySearchResponse(id, latestUpdatedTime, name, url, apiName, type, posterUrl, year, syncData, quality, posterHeaders) {
override var posterHeaders: Map<String, String>? = null,
override val plot: String? = null,
override val rating: Int? = null,
override val tags: List<String>? = null,
) : LibrarySearchResponse(id, latestUpdatedTime, name, url, apiName, type, posterUrl, year, syncData, quality, posterHeaders, plot) {
fun toLibraryItem(id: String): SyncAPI.LibraryItem {
return SyncAPI.LibraryItem(
name,
@ -264,7 +273,7 @@ object DataStoreHelper {
null,
null,
latestUpdatedTime,
apiName, type, posterUrl, posterHeaders, quality, this.id
apiName, type, posterUrl, posterHeaders, quality, this.id, plot = this.plot, rating = this.rating, tags = this.tags
)
}
}
@ -281,8 +290,11 @@ object DataStoreHelper {
override val year: Int?,
override val syncData: Map<String, String>? = null,
override var quality: SearchQuality? = null,
override var posterHeaders: Map<String, String>? = null
) : LibrarySearchResponse(id, latestUpdatedTime, name, url, apiName, type, posterUrl, year, syncData, quality, posterHeaders) {
override var posterHeaders: Map<String, String>? = null,
override val plot: String? = null,
override val rating: Int? = null,
override val tags: List<String>? = null,
) : LibrarySearchResponse(id, latestUpdatedTime, name, url, apiName, type, posterUrl, year, syncData, quality, posterHeaders,plot) {
fun toLibraryItem(): SyncAPI.LibraryItem? {
return SyncAPI.LibraryItem(
name,
@ -292,7 +304,7 @@ object DataStoreHelper {
null,
null,
latestUpdatedTime,
apiName, type, posterUrl, posterHeaders, quality, this.id
apiName, type, posterUrl, posterHeaders, quality, this.id, plot = this.plot, rating = this.rating, tags = this.tags
)
}
}