Initial commit

This commit is contained in:
Finnley Somdahl 2023-10-17 18:42:43 -05:00
commit 21bfbfb139
520 changed files with 47819 additions and 0 deletions

View file

@ -0,0 +1,279 @@
package ani.dantotsu.media
import android.app.Activity
import android.os.Handler
import android.os.Looper
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.media.anime.Episode
import ani.dantotsu.media.anime.SelectorDialogFragment
import ani.dantotsu.loadData
import ani.dantotsu.logger
import ani.dantotsu.media.manga.MangaChapter
import ani.dantotsu.others.AniSkip
import ani.dantotsu.others.Jikan
import ani.dantotsu.others.Kitsu
import ani.dantotsu.parsers.Book
import ani.dantotsu.parsers.MangaImage
import ani.dantotsu.parsers.MangaReadSources
import ani.dantotsu.parsers.NovelSources
import ani.dantotsu.parsers.ShowResponse
import ani.dantotsu.parsers.VideoExtractor
import ani.dantotsu.parsers.WatchSources
import ani.dantotsu.saveData
import ani.dantotsu.snackString
import ani.dantotsu.tryWithSuspend
import ani.dantotsu.currContext
import ani.dantotsu.R
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
class MediaDetailsViewModel : ViewModel() {
val scrolledToTop = MutableLiveData(true)
fun saveSelected(id: Int, data: Selected, activity: Activity? = null) {
saveData("$id-select", data, activity)
}
fun loadSelected(media: Media): Selected {
return loadData<Selected>("${media.id}-select") ?: Selected().let {
it.source = if (media.isAdult) 0 else when (media.anime != null) {
true -> loadData("settings_def_anime_source") ?: 0
else -> loadData("settings_def_manga_source") ?: 0
}
it.preferDub = loadData("settings_prefer_dub") ?: false
saveSelected(media.id, it)
it
}
}
var continueMedia: Boolean? = null
private var loading = false
private val media: MutableLiveData<Media> = MutableLiveData<Media>(null)
fun getMedia(): LiveData<Media> = media
fun loadMedia(m: Media) {
if (!loading) {
loading = true
media.postValue(Anilist.query.mediaDetails(m))
}
loading = false
}
fun setMedia(m: Media) {
media.postValue(m)
}
val responses = MutableLiveData<List<ShowResponse>?>(null)
//Anime
private val kitsuEpisodes: MutableLiveData<Map<String, Episode>> = MutableLiveData<Map<String, Episode>>(null)
fun getKitsuEpisodes(): LiveData<Map<String, Episode>> = kitsuEpisodes
suspend fun loadKitsuEpisodes(s: Media) {
tryWithSuspend {
if (kitsuEpisodes.value == null) kitsuEpisodes.postValue(Kitsu.getKitsuEpisodesDetails(s))
}
}
private val fillerEpisodes: MutableLiveData<Map<String, Episode>> = MutableLiveData<Map<String, Episode>>(null)
fun getFillerEpisodes(): LiveData<Map<String, Episode>> = fillerEpisodes
suspend fun loadFillerEpisodes(s: Media) {
tryWithSuspend {
if (fillerEpisodes.value == null) fillerEpisodes.postValue(
Jikan.getEpisodes(
s.idMAL ?: return@tryWithSuspend
)
)
}
}
var watchSources: WatchSources? = null
private val episodes = MutableLiveData<MutableMap<Int, MutableMap<String, Episode>>>(null)
private val epsLoaded = mutableMapOf<Int, MutableMap<String, Episode>>()
fun getEpisodes(): LiveData<MutableMap<Int, MutableMap<String, Episode>>> = episodes
suspend fun loadEpisodes(media: Media, i: Int) {
if (!epsLoaded.containsKey(i)) {
epsLoaded[i] = watchSources?.loadEpisodesFromMedia(i, media) ?: return
}
episodes.postValue(epsLoaded)
}
suspend fun forceLoadEpisode(media: Media, i: Int) {
epsLoaded[i] = watchSources?.loadEpisodesFromMedia(i, media) ?: return
episodes.postValue(epsLoaded)
}
suspend fun overrideEpisodes(i: Int, source: ShowResponse, id: Int) {
watchSources?.saveResponse(i, id, source)
epsLoaded[i] = watchSources?.loadEpisodes(i, source.link, source.extra, source.sAnime) ?: return
episodes.postValue(epsLoaded)
}
private var episode = MutableLiveData<Episode?>(null)
fun getEpisode(): LiveData<Episode?> = episode
suspend fun loadEpisodeVideos(ep: Episode, i: Int, post: Boolean = true) {
val link = ep.link ?: return
if (!ep.allStreams || ep.extractors.isNullOrEmpty()) {
val list = mutableListOf<VideoExtractor>()
ep.extractors = list
watchSources?.get(i)?.apply {
if (!post && !allowsPreloading) return@apply
ep.sEpisode?.let {
loadByVideoServers(link, ep.extra, it) {
if (it.videos.isNotEmpty()) {
list.add(it)
ep.extractorCallback?.invoke(it)
}
}
}
ep.extractorCallback = null
if (list.isNotEmpty())
ep.allStreams = true
}
}
if (post) {
episode.postValue(ep)
MainScope().launch(Dispatchers.Main) {
episode.value = null
}
}
}
val timeStamps = MutableLiveData<List<AniSkip.Stamp>?>()
private val timeStampsMap: MutableMap<Int, List<AniSkip.Stamp>?> = mutableMapOf()
suspend fun loadTimeStamps(malId: Int?, episodeNum: Int?, duration: Long, useProxyForTimeStamps: Boolean) {
malId ?: return
episodeNum ?: return
if (timeStampsMap.containsKey(episodeNum))
return timeStamps.postValue(timeStampsMap[episodeNum])
val result = AniSkip.getResult(malId, episodeNum, duration, useProxyForTimeStamps)
timeStampsMap[episodeNum] = result
timeStamps.postValue(result)
}
suspend fun loadEpisodeSingleVideo(ep: Episode, selected: Selected, post: Boolean = true): Boolean {
if (ep.extractors.isNullOrEmpty()) {
val server = selected.server ?: return false
val link = ep.link ?: return false
ep.extractors = mutableListOf(watchSources?.get(selected.source)?.let {
if (!post && !it.allowsPreloading) null
else ep.sEpisode?.let { it1 ->
it.loadSingleVideoServer(server, link, ep.extra,
it1, post)
}
} ?: return false)
ep.allStreams = false
}
if (post) {
episode.postValue(ep)
MainScope().launch(Dispatchers.Main) {
episode.value = null
}
}
return true
}
fun setEpisode(ep: Episode?, who: String) {
logger("set episode ${ep?.number} - $who", false)
episode.postValue(ep)
MainScope().launch(Dispatchers.Main) {
episode.value = null
}
}
val epChanged = MutableLiveData(true)
fun onEpisodeClick(media: Media, i: String, manager: FragmentManager, launch: Boolean = true, prevEp: String? = null) {
Handler(Looper.getMainLooper()).post {
if (manager.findFragmentByTag("dialog") == null && !manager.isDestroyed) {
if (media.anime?.episodes?.get(i) != null) {
media.anime.selectedEpisode = i
} else {
snackString(currContext()?.getString(R.string.episode_not_found, i))
return@post
}
media.selected = this.loadSelected(media)
val selector = SelectorDialogFragment.newInstance(media.selected!!.server, launch, prevEp)
selector.show(manager, "dialog")
}
}
}
//Manga
var mangaReadSources: MangaReadSources? = null
private val mangaChapters = MutableLiveData<MutableMap<Int, MutableMap<String, MangaChapter>>>(null)
private val mangaLoaded = mutableMapOf<Int, MutableMap<String, MangaChapter>>()
fun getMangaChapters(): LiveData<MutableMap<Int, MutableMap<String, MangaChapter>>> = mangaChapters
suspend fun loadMangaChapters(media: Media, i: Int) {
logger("Loading Manga Chapters : $mangaLoaded")
if (!mangaLoaded.containsKey(i)) tryWithSuspend {
mangaLoaded[i] = mangaReadSources?.loadChaptersFromMedia(i, media) ?: return@tryWithSuspend
}
mangaChapters.postValue(mangaLoaded)
}
suspend fun overrideMangaChapters(i: Int, source: ShowResponse, id: Int) {
mangaReadSources?.saveResponse(i, id, source)
tryWithSuspend {
mangaLoaded[i] = mangaReadSources?.loadChapters(i, source) ?: return@tryWithSuspend
}
mangaChapters.postValue(mangaLoaded)
}
private val mangaChapter = MutableLiveData<MangaChapter?>(null)
fun getMangaChapter(): LiveData<MangaChapter?> = mangaChapter
suspend fun loadMangaChapterImages(chapter: MangaChapter, selected: Selected, post: Boolean = true): Boolean {
return tryWithSuspend(true) {
chapter.addImages(
mangaReadSources?.get(selected.source)?.loadImages(chapter.link) ?: return@tryWithSuspend false
)
if (post) mangaChapter.postValue(chapter)
true
} ?: false
}
fun loadTransformation(mangaImage: MangaImage, source: Int): BitmapTransformation? {
return if (mangaImage.useTransformation) mangaReadSources?.get(source)?.getTransformation() else null
}
val novelSources = NovelSources
val novelResponses = MutableLiveData<List<ShowResponse>>(null)
suspend fun searchNovels(query: String, i: Int) {
val source = novelSources[i]
tryWithSuspend(post = true) {
if (source != null) {
novelResponses.postValue(source.search(query))
}
}
}
suspend fun autoSearchNovels(media: Media) {
val source = novelSources[media.selected?.source ?: 0]
tryWithSuspend(post = true) {
if (source != null) {
novelResponses.postValue(source.sortedSearch(media))
}
}
}
val book: MutableLiveData<Book> = MutableLiveData(null)
suspend fun loadBook(novel: ShowResponse, i: Int) {
tryWithSuspend {
book.postValue(novelSources[i]?.loadBook(novel.link, novel.extra) ?: return@tryWithSuspend)
}
}
}