package com.lagradost.cloudstream3.ui.player import android.util.Log import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.lagradost.cloudstream3.mvvm.Resource import com.lagradost.cloudstream3.mvvm.launchSafe import com.lagradost.cloudstream3.mvvm.normalSafeApiCall import com.lagradost.cloudstream3.mvvm.safeApiCall import com.lagradost.cloudstream3.ui.result.ResultEpisode import com.lagradost.cloudstream3.utils.Coroutines.ioSafe import com.lagradost.cloudstream3.utils.EpisodeSkip import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorUri import kotlinx.coroutines.Job class PlayerGeneratorViewModel : ViewModel() { companion object { val TAG = "PlayViewGen" } private var generator: IGenerator? = null private val _currentLinks = MutableLiveData>>(setOf()) val currentLinks: LiveData>> = _currentLinks private val _currentSubs = MutableLiveData>(setOf()) val currentSubs: LiveData> = _currentSubs private val _loadingLinks = MutableLiveData>() val loadingLinks: LiveData> = _loadingLinks private val _currentStamps = MutableLiveData>(emptyList()) val currentStamps: LiveData> = _currentStamps private val _currentSubtitleYear = MutableLiveData(null) val currentSubtitleYear: LiveData = _currentSubtitleYear fun setSubtitleYear(year: Int?) { _currentSubtitleYear.postValue(year) } fun getId(): Int? { return generator?.getCurrentId() } fun loadLinks(episode: Int) { generator?.goto(episode) loadLinks() } fun loadLinksPrev() { Log.i(TAG, "loadLinksPrev") if (generator?.hasPrev() == true) { generator?.prev() loadLinks() } } fun loadLinksNext() { Log.i(TAG, "loadLinksNext") if (generator?.hasNext() == true) { generator?.next() loadLinks() } } fun hasNextEpisode(): Boolean? { return generator?.hasNext() } fun preLoadNextLinks() { Log.i(TAG, "preLoadNextLinks") currentJob?.cancel() currentJob = viewModelScope.launchSafe { if (generator?.hasCache == true && generator?.hasNext() == true) { safeApiCall { generator?.generateLinks( clearCache = false, isCasting = false, {}, {}, offset = 1 ) } } } } fun getMeta(): Any? { return normalSafeApiCall { generator?.getCurrent() } } fun getAllMeta(): List? { return normalSafeApiCall { generator?.getAll() } } fun getNextMeta(): Any? { return normalSafeApiCall { if (generator?.hasNext() == false) return@normalSafeApiCall null generator?.getCurrent(offset = 1) } } fun attachGenerator(newGenerator: IGenerator?) { if (generator == null) { generator = newGenerator } } /** * If duplicate nothing will happen * */ fun addSubtitles(file: Set) { val currentSubs = _currentSubs.value ?: emptySet() // Prevent duplicates val allSubs = (currentSubs + file).distinct().toSet() // Do not post if there's nothing new // Posting will refresh subtitles which will in turn // make the subs to english if previously unselected if (allSubs != currentSubs) { _currentSubs.postValue(allSubs) } } private var currentJob: Job? = null private var currentStampJob: Job? = null fun loadStamps(duration: Long) { //currentStampJob?.cancel() currentStampJob = ioSafe { val meta = generator?.getCurrent() val page = (generator as? RepoLinkGenerator?)?.page if (page != null && meta is ResultEpisode) { _currentStamps.postValue(listOf()) _currentStamps.postValue( EpisodeSkip.getStamps( page, meta, duration, hasNextEpisode() ?: false ) ) } } } fun loadLinks(clearCache: Boolean = false, isCasting: Boolean = false) { Log.i(TAG, "loadLinks") currentJob?.cancel() currentJob = viewModelScope.launchSafe { val currentLinks = mutableSetOf>() val currentSubs = mutableSetOf() // clear old data _currentSubs.postValue(currentSubs) _currentLinks.postValue(currentLinks) // load more data _loadingLinks.postValue(Resource.Loading()) val loadingState = safeApiCall { generator?.generateLinks(clearCache = clearCache, isCasting = isCasting, { currentLinks.add(it) _currentLinks.postValue(currentLinks) }, { currentSubs.add(it) // _currentSubs.postValue(currentSubs) // this causes ConcurrentModificationException, so fuck it }) } _loadingLinks.postValue(loadingState) _currentLinks.postValue(currentLinks) _currentSubs.postValue( currentSubs.union(_currentSubs.value ?: emptySet()) ) } } }