ananas/app/src/main/java/dev/jdtech/jellyfin/viewmodels/EpisodeBottomSheetViewModel.kt
2022-01-21 17:39:28 +01:00

192 lines
No EOL
6.2 KiB
Kotlin

package dev.jdtech.jellyfin.viewmodels
import android.app.Application
import android.net.Uri
import android.os.Build
import androidx.lifecycle.*
import dagger.hilt.android.lifecycle.HiltViewModel
import dev.jdtech.jellyfin.database.DownloadDatabaseDao
import dev.jdtech.jellyfin.models.DownloadRequestItem
import dev.jdtech.jellyfin.models.PlayerItem
import dev.jdtech.jellyfin.repository.JellyfinRepository
import dev.jdtech.jellyfin.utils.*
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import org.jellyfin.sdk.api.client.exception.ApiClientException
import org.jellyfin.sdk.model.api.BaseItemDto
import timber.log.Timber
import java.text.DateFormat
import java.time.ZoneOffset
import java.util.Date
import java.util.UUID
import javax.inject.Inject
@HiltViewModel
class EpisodeBottomSheetViewModel
@Inject
constructor(
private val application: Application,
private val jellyfinRepository: JellyfinRepository,
private val downloadDatabase: DownloadDatabaseDao
) : ViewModel() {
private val uiState = MutableStateFlow<UiState>(UiState.Loading)
sealed class UiState {
data class Normal(
val episode: BaseItemDto,
val runTime: String,
val dateString: String,
val played: Boolean,
val favorite: Boolean,
val canDownload: Boolean,
val downloaded: Boolean,
val downloadEpisode: Boolean,
val available: Boolean,
) : UiState()
object Loading : UiState()
data class Error(val message: String?) : UiState()
}
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
scope.launch { uiState.collect { collector(it) } }
}
var item: BaseItemDto? = null
private var runTime: String = ""
private var dateString: String = ""
var played: Boolean = false
var favorite: Boolean = false
private var canDownload = false
private var downloaded: Boolean = false
private var downloadEpisode: Boolean = false
private var available: Boolean = true
var playerItems: MutableList<PlayerItem> = mutableListOf()
private lateinit var downloadRequestItem: DownloadRequestItem
fun loadEpisode(episodeId: UUID) {
viewModelScope.launch {
uiState.emit(UiState.Loading)
try {
val tempItem = jellyfinRepository.getItem(episodeId)
item = tempItem
runTime = "${tempItem.runTimeTicks?.div(600000000)} min"
dateString = getDateString(tempItem)
played = tempItem.userData?.played == true
favorite = tempItem.userData?.isFavorite == true
canDownload = tempItem.canDownload == true
downloaded = isItemDownloaded(downloadDatabase, episodeId)
uiState.emit(
UiState.Normal(
tempItem,
runTime,
dateString,
played,
favorite,
canDownload,
downloaded,
downloadEpisode,
available,
)
)
} catch (e: Exception) {
uiState.emit(UiState.Error(e.message))
}
}
}
fun loadEpisode(playerItem: PlayerItem) {
viewModelScope.launch {
uiState.emit(UiState.Loading)
playerItems.add(playerItem)
item = downloadMetadataToBaseItemDto(playerItem.item!!)
available = isItemAvailable(playerItem.itemId)
Timber.d("Available: $available")
uiState.emit(
UiState.Normal(
item!!,
runTime,
dateString,
played,
favorite,
canDownload,
downloaded,
downloadEpisode,
available,
)
)
}
}
fun markAsPlayed(itemId: UUID) {
viewModelScope.launch {
try {
jellyfinRepository.markAsPlayed(itemId)
} catch (e: ApiClientException) {
Timber.d(e)
}
}
played = true
}
fun markAsUnplayed(itemId: UUID) {
viewModelScope.launch {
try {
jellyfinRepository.markAsUnplayed(itemId)
} catch (e: ApiClientException) {
Timber.d(e)
}
}
played = false
}
fun markAsFavorite(itemId: UUID) {
viewModelScope.launch {
try {
jellyfinRepository.markAsFavorite(itemId)
} catch (e: ApiClientException) {
Timber.d(e)
}
}
favorite = true
}
fun unmarkAsFavorite(itemId: UUID) {
viewModelScope.launch {
try {
jellyfinRepository.unmarkAsFavorite(itemId)
} catch (e: ApiClientException) {
Timber.d(e)
}
}
favorite = false
}
fun loadDownloadRequestItem(itemId: UUID) {
viewModelScope.launch {
val episode = item
val uri = jellyfinRepository.getStreamUrl(itemId, episode?.mediaSources?.get(0)?.id!!)
val metadata = baseItemDtoToDownloadMetadata(episode)
downloadRequestItem = DownloadRequestItem(uri, itemId, metadata)
downloadEpisode = true
requestDownload(downloadDatabase, Uri.parse(downloadRequestItem.uri), downloadRequestItem, application)
}
}
fun deleteEpisode() {
deleteDownloadedEpisode(downloadDatabase, playerItems[0].itemId)
}
private fun getDateString(item: BaseItemDto): String {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val instant = item.premiereDate?.toInstant(ZoneOffset.UTC)
val date = Date.from(instant)
DateFormat.getDateInstance(DateFormat.SHORT).format(date)
} else {
// TODO: Implement a way to get the year from LocalDateTime in Android < O
item.premiereDate.toString()
}
}
}