Teapod is a unofficial App for Crunchyroll
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
4.1 KiB

/**
* Teapod
*
* Copyright 2020-2022 <seil0@mosad.xyz>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
package org.mosad.teapod.ui.activity.main.viewmodel
import androidx.lifecycle.LifecycleCoroutineScope
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import org.mosad.teapod.parser.crunchyroll.*
import kotlin.random.Random
class HomeViewModel : ViewModel() {
private val uiState = MutableStateFlow<UiState>(UiState.Loading)
sealed class UiState {
object Loading : UiState()
data class Normal(
val upNextItems: List<ContinueWatchingItem>,
val watchlistItems: List<Item>,
val recentlyAddedItems: List<Item>,
val topTenItems: List<Item>,
val highlightItem: Item,
val highlightIsWatchlist:Boolean
) : UiState()
data class Error(val message: String?) : UiState()
}
init {
load()
}
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
scope.launch { uiState.collect { collector(it) } }
}
fun load() {
viewModelScope.launch {
uiState.emit(UiState.Loading)
try {
// run the loading in parallel to speed up the process
val upNextJob = viewModelScope.async { Crunchyroll.upNextAccount().items }
val watchlistJob = viewModelScope.async { Crunchyroll.watchlist(50).items }
val recentlyAddedJob = viewModelScope.async {
Crunchyroll.browse(sortBy = SortBy.NEWLY_ADDED, n = 50).items
}
val topTenJob = viewModelScope.async {
Crunchyroll.browse(sortBy = SortBy.POPULARITY, n = 10).items
}
val recentlyAddedItems = recentlyAddedJob.await()
// FIXME crashes on newTitles.items.size == 0
val highlightItem = recentlyAddedItems[Random.nextInt(recentlyAddedItems.size)]
val highlightItemIsWatchlist = Crunchyroll.isWatchlist(highlightItem.id)
uiState.emit(UiState.Normal(
upNextJob.await(), watchlistJob.await(), recentlyAddedJob.await(),
topTenJob.await(), highlightItem, highlightItemIsWatchlist
))
} catch (e: Exception) {
uiState.emit(UiState.Error(e.message))
}
}
}
/**
* Toggle the watchlist state of the highlight media.
*/
fun toggleHighlightWatchlist() {
viewModelScope.launch {
uiState.update { currentUiState ->
if (currentUiState is UiState.Normal) {
if (currentUiState.highlightIsWatchlist) {
Crunchyroll.deleteWatchlist(currentUiState.highlightItem.id)
} else {
Crunchyroll.postWatchlist(currentUiState.highlightItem.id)
}
// update the watchlist after a item has been added/removed
val watchlistItems = Crunchyroll.watchlist(50).items
currentUiState.copy(
watchlistItems = watchlistItems,
highlightIsWatchlist = !currentUiState.highlightIsWatchlist)
} else {
currentUiState
}
}
}
}
}

Du besuchst diese Seite mit einem veralteten IPv4-Internetzugang. Möglicherweise treten in Zukunft Probleme mit der Erreichbarkeit und Performance auf. Bitte frage deinen Internetanbieter oder Netzwerkadministrator nach IPv6-Unterstützung.
You are visiting this site with an outdated IPv4 internet access. You may experience problems with accessibility and performance in the future. Please ask your ISP or network administrator for IPv6 support.
Weitere Infos | More Information
Klicke zum schließen | Click to close