126 lines
4.6 KiB
Kotlin
126 lines
4.6 KiB
Kotlin
/**
|
|
* 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 recommendationsItems: List<Item>,
|
|
val recentlyAddedItems: List<Item>,
|
|
val topTenItems: List<Item>,
|
|
val highlightItem: Item,
|
|
val highlightItemUpNext: UpNextSeriesItem,
|
|
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 recommendationsJob = viewModelScope.async {
|
|
Crunchyroll.recommendations(20).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 highlightItemUpNextJob = viewModelScope.async {
|
|
Crunchyroll.upNextSeries(highlightItem.id)
|
|
}
|
|
val highlightItemIsWatchlistJob = viewModelScope.async {
|
|
Crunchyroll.isWatchlist(highlightItem.id)
|
|
}
|
|
|
|
uiState.emit(UiState.Normal(
|
|
upNextJob.await(), watchlistJob.await(), recommendationsJob.await(),
|
|
recentlyAddedJob.await(), topTenJob.await(), highlightItem,
|
|
highlightItemUpNextJob.await(), highlightItemIsWatchlistJob.await()
|
|
))
|
|
} 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
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} |