2021-04-30 17:20:15 +00:00
|
|
|
package com.lagradost.cloudstream3.ui.home
|
|
|
|
|
2021-07-30 21:03:46 +00:00
|
|
|
import android.content.Context
|
2021-04-30 17:20:15 +00:00
|
|
|
import androidx.lifecycle.LiveData
|
|
|
|
import androidx.lifecycle.MutableLiveData
|
|
|
|
import androidx.lifecycle.ViewModel
|
2021-07-29 00:19:42 +00:00
|
|
|
import androidx.lifecycle.viewModelScope
|
|
|
|
import com.lagradost.cloudstream3.APIHolder.apis
|
|
|
|
import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
|
2021-11-05 22:08:47 +00:00
|
|
|
import com.lagradost.cloudstream3.AcraApplication.Companion.context
|
2021-07-29 00:19:42 +00:00
|
|
|
import com.lagradost.cloudstream3.HomePageResponse
|
2021-07-29 15:16:08 +00:00
|
|
|
import com.lagradost.cloudstream3.MainAPI
|
2021-07-30 21:03:46 +00:00
|
|
|
import com.lagradost.cloudstream3.SearchResponse
|
2021-07-29 00:19:42 +00:00
|
|
|
import com.lagradost.cloudstream3.mvvm.Resource
|
|
|
|
import com.lagradost.cloudstream3.ui.APIRepository
|
2021-09-05 11:56:25 +00:00
|
|
|
import com.lagradost.cloudstream3.ui.APIRepository.Companion.noneApi
|
|
|
|
import com.lagradost.cloudstream3.ui.APIRepository.Companion.randomApi
|
2021-07-30 21:03:46 +00:00
|
|
|
import com.lagradost.cloudstream3.ui.WatchType
|
2021-11-05 22:08:47 +00:00
|
|
|
import com.lagradost.cloudstream3.utils.*
|
2021-08-25 15:28:25 +00:00
|
|
|
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
2021-11-05 22:08:47 +00:00
|
|
|
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
2021-08-25 15:28:25 +00:00
|
|
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getAllResumeStateIds
|
2021-07-30 21:03:46 +00:00
|
|
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getAllWatchStateIds
|
|
|
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getBookmarkedData
|
2021-08-25 15:28:25 +00:00
|
|
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getLastWatched
|
2021-07-30 21:03:46 +00:00
|
|
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getResultWatchState
|
2021-08-25 15:28:25 +00:00
|
|
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
2021-07-30 21:03:46 +00:00
|
|
|
import kotlinx.coroutines.Dispatchers
|
2021-08-25 15:28:25 +00:00
|
|
|
import kotlinx.coroutines.Job
|
2021-07-29 00:19:42 +00:00
|
|
|
import kotlinx.coroutines.launch
|
2021-07-30 21:03:46 +00:00
|
|
|
import kotlinx.coroutines.withContext
|
2021-12-09 21:20:27 +00:00
|
|
|
import java.util.*
|
2021-04-30 17:20:15 +00:00
|
|
|
|
|
|
|
class HomeViewModel : ViewModel() {
|
2021-10-19 20:17:06 +00:00
|
|
|
private var repo: APIRepository? = null
|
2021-04-30 17:20:15 +00:00
|
|
|
|
2021-07-29 00:19:42 +00:00
|
|
|
private val _apiName = MutableLiveData<String>()
|
|
|
|
val apiName: LiveData<String> = _apiName
|
|
|
|
|
|
|
|
private val _page = MutableLiveData<Resource<HomePageResponse>>()
|
|
|
|
val page: LiveData<Resource<HomePageResponse>> = _page
|
|
|
|
|
2021-11-25 22:36:35 +00:00
|
|
|
private val _randomItems = MutableLiveData<List<SearchResponse>?>(null)
|
|
|
|
val randomItems: LiveData<List<SearchResponse>?> = _randomItems
|
|
|
|
|
2021-07-29 00:19:42 +00:00
|
|
|
private fun autoloadRepo(): APIRepository {
|
|
|
|
return APIRepository(apis.first { it.hasMainPage })
|
|
|
|
}
|
|
|
|
|
2021-12-09 21:20:27 +00:00
|
|
|
private val _availableWatchStatusTypes = MutableLiveData<Pair<EnumSet<WatchType>, EnumSet<WatchType>>>()
|
|
|
|
val availableWatchStatusTypes: LiveData<Pair<EnumSet<WatchType>, EnumSet<WatchType>>> = _availableWatchStatusTypes
|
|
|
|
private val _bookmarks = MutableLiveData<Pair<Boolean, List<SearchResponse>>>()
|
|
|
|
val bookmarks: LiveData<Pair<Boolean, List<SearchResponse>>> = _bookmarks
|
2021-07-30 21:03:46 +00:00
|
|
|
|
2021-08-25 15:28:25 +00:00
|
|
|
private val _resumeWatching = MutableLiveData<List<SearchResponse>>()
|
|
|
|
val resumeWatching: LiveData<List<SearchResponse>> = _resumeWatching
|
|
|
|
|
|
|
|
fun loadResumeWatching(context: Context) = viewModelScope.launch {
|
|
|
|
val resumeWatching = withContext(Dispatchers.IO) {
|
|
|
|
context.getAllResumeStateIds().mapNotNull { id ->
|
|
|
|
context.getLastWatched(id)
|
|
|
|
}.sortedBy { -it.updateTime }
|
|
|
|
}
|
|
|
|
|
|
|
|
// val resumeWatchingResult = ArrayList<DataStoreHelper.ResumeWatchingResult>()
|
|
|
|
|
|
|
|
val resumeWatchingResult = withContext(Dispatchers.IO) {
|
|
|
|
resumeWatching.map { resume ->
|
|
|
|
val data = context.getKey<VideoDownloadHelper.DownloadHeaderCached>(
|
|
|
|
DOWNLOAD_HEADER_CACHE,
|
|
|
|
resume.parentId.toString()
|
|
|
|
) ?: return@map null
|
|
|
|
val watchPos = context.getViewPos(resume.episodeId)
|
|
|
|
DataStoreHelper.ResumeWatchingResult(
|
|
|
|
data.name,
|
|
|
|
data.url,
|
|
|
|
data.apiName,
|
|
|
|
data.type,
|
|
|
|
data.poster,
|
|
|
|
watchPos,
|
|
|
|
resume.episodeId,
|
|
|
|
resume.parentId,
|
|
|
|
resume.episode,
|
|
|
|
resume.season,
|
|
|
|
resume.isFromDownload
|
|
|
|
)
|
|
|
|
}.filterNotNull()
|
|
|
|
}
|
|
|
|
|
|
|
|
_resumeWatching.postValue(resumeWatchingResult)
|
|
|
|
}
|
|
|
|
|
2021-12-09 21:20:27 +00:00
|
|
|
fun loadStoredData(context: Context, preferredWatchStatus: EnumSet<WatchType>?) = viewModelScope.launch {
|
2021-07-30 21:03:46 +00:00
|
|
|
val watchStatusIds = withContext(Dispatchers.IO) {
|
|
|
|
context.getAllWatchStateIds().map { id ->
|
|
|
|
Pair(id, context.getResultWatchState(id))
|
|
|
|
}
|
2021-07-30 23:41:54 +00:00
|
|
|
}.distinctBy { it.first }
|
2021-07-30 21:03:46 +00:00
|
|
|
val length = WatchType.values().size
|
2021-12-09 21:20:27 +00:00
|
|
|
val currentWatchTypes = EnumSet.noneOf(WatchType::class.java)
|
2021-07-30 21:03:46 +00:00
|
|
|
|
|
|
|
for (watch in watchStatusIds) {
|
|
|
|
currentWatchTypes.add(watch.second)
|
|
|
|
if (currentWatchTypes.size >= length) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-30 23:41:54 +00:00
|
|
|
currentWatchTypes.remove(WatchType.NONE)
|
|
|
|
|
2021-07-30 21:03:46 +00:00
|
|
|
if (currentWatchTypes.size <= 0) {
|
2021-12-09 21:20:27 +00:00
|
|
|
_bookmarks.postValue(Pair(false, ArrayList()))
|
2021-07-30 21:03:46 +00:00
|
|
|
return@launch
|
|
|
|
}
|
|
|
|
|
2021-12-09 21:20:27 +00:00
|
|
|
val watchPrefNotNull = preferredWatchStatus ?: EnumSet.of(currentWatchTypes.first())
|
|
|
|
//if (currentWatchTypes.any { watchPrefNotNull.contains(it) }) watchPrefNotNull else listOf(currentWatchTypes.first())
|
|
|
|
|
2021-07-30 23:41:54 +00:00
|
|
|
_availableWatchStatusTypes.postValue(
|
2021-07-30 21:03:46 +00:00
|
|
|
Pair(
|
2021-12-09 21:20:27 +00:00
|
|
|
watchPrefNotNull,
|
|
|
|
currentWatchTypes,
|
2021-07-30 21:03:46 +00:00
|
|
|
)
|
|
|
|
)
|
2021-12-09 21:20:27 +00:00
|
|
|
|
2021-07-30 21:03:46 +00:00
|
|
|
val list = withContext(Dispatchers.IO) {
|
2021-12-09 21:20:27 +00:00
|
|
|
watchStatusIds.filter { watchPrefNotNull.contains(it.second) }
|
2021-07-30 23:41:54 +00:00
|
|
|
.mapNotNull { context.getBookmarkedData(it.first) }
|
|
|
|
.sortedBy { -it.latestUpdatedTime }
|
2021-07-30 21:03:46 +00:00
|
|
|
}
|
2021-12-09 21:20:27 +00:00
|
|
|
_bookmarks.postValue(Pair(true,list))
|
2021-07-30 21:03:46 +00:00
|
|
|
}
|
|
|
|
|
2021-10-19 20:17:06 +00:00
|
|
|
private var onGoingLoad: Job? = null
|
2021-10-09 21:59:37 +00:00
|
|
|
private fun loadAndCancel(api: MainAPI?) {
|
2021-08-25 15:28:25 +00:00
|
|
|
onGoingLoad?.cancel()
|
|
|
|
onGoingLoad = load(api)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun load(api: MainAPI?) = viewModelScope.launch {
|
2021-09-05 11:56:25 +00:00
|
|
|
repo = if (api != null) {
|
2021-07-29 00:19:42 +00:00
|
|
|
APIRepository(api)
|
|
|
|
} else {
|
|
|
|
autoloadRepo()
|
|
|
|
}
|
2021-10-09 21:59:37 +00:00
|
|
|
|
2021-07-29 15:44:16 +00:00
|
|
|
_apiName.postValue(repo?.name)
|
2021-11-27 18:49:51 +00:00
|
|
|
_randomItems.postValue(listOf())
|
|
|
|
|
2021-09-05 11:56:25 +00:00
|
|
|
if (repo?.hasMainPage == true) {
|
|
|
|
_page.postValue(Resource.Loading())
|
2021-11-25 22:36:35 +00:00
|
|
|
|
|
|
|
val data = repo?.getMainPage()
|
|
|
|
when (data) {
|
|
|
|
is Resource.Success -> {
|
|
|
|
val home = data.value
|
|
|
|
if (home.items.isNotEmpty()) {
|
|
|
|
val currentList =
|
|
|
|
home.items.shuffled().filter { !it.list.isNullOrEmpty() }.flatMap { it.list }
|
|
|
|
.distinctBy { it.url }
|
|
|
|
.toList()
|
|
|
|
|
|
|
|
if (!currentList.isNullOrEmpty()) {
|
|
|
|
val randomItems = currentList.shuffled()
|
|
|
|
|
|
|
|
_randomItems.postValue(randomItems)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else -> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_page.postValue(data)
|
2021-09-05 11:56:25 +00:00
|
|
|
} else {
|
|
|
|
_page.postValue(Resource.Success(HomePageResponse(emptyList())))
|
|
|
|
}
|
2021-04-30 17:20:15 +00:00
|
|
|
}
|
2021-07-29 15:16:08 +00:00
|
|
|
|
2021-10-31 17:51:39 +00:00
|
|
|
fun loadAndCancel(preferredApiName: String?, currentPrefMedia: Int) = viewModelScope.launch {
|
2021-07-29 15:16:08 +00:00
|
|
|
val api = getApiFromNameNull(preferredApiName)
|
2021-09-05 11:56:25 +00:00
|
|
|
if (preferredApiName == noneApi.name)
|
|
|
|
loadAndCancel(noneApi)
|
2021-11-25 22:36:35 +00:00
|
|
|
else if (preferredApiName == randomApi.name || api == null) {
|
|
|
|
val validAPIs = AppUtils.filterProviderByPreferredMedia(apis, currentPrefMedia)
|
2021-11-05 22:08:47 +00:00
|
|
|
val apiRandom = validAPIs.random()
|
|
|
|
loadAndCancel(apiRandom)
|
|
|
|
context?.setKey(HOMEPAGE_API, apiRandom.name)
|
2021-09-05 11:56:25 +00:00
|
|
|
} else {
|
|
|
|
loadAndCancel(api)
|
|
|
|
}
|
2021-07-29 15:16:08 +00:00
|
|
|
}
|
2021-04-30 17:20:15 +00:00
|
|
|
}
|