feat: add DownloadsViewModel for managing offline media downloads

This commit is contained in:
2026-02-22 13:41:47 +01:00
parent ce126988d9
commit d5c0bbded6
3 changed files with 110 additions and 18 deletions

View File

@@ -1,39 +1,71 @@
package hu.bbara.purefin.app.home.ui
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Download
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import hu.bbara.purefin.common.ui.PosterCard
import hu.bbara.purefin.feature.shared.download.DownloadsViewModel
@Composable
fun DownloadsContent(
modifier: Modifier = Modifier,
viewModel: DownloadsViewModel = hiltViewModel(),
) {
Column(
modifier = modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Icon(
imageVector = Icons.Outlined.Download,
contentDescription = null,
modifier = Modifier.size(64.dp),
tint = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = "No downloads yet",
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier
)
val downloads = viewModel.downloads.collectAsState(emptyList())
if (downloads.value.isEmpty()) {
Column(
modifier = modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Icon(
imageVector = Icons.Outlined.Download,
contentDescription = null,
modifier = Modifier.size(64.dp),
tint = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = "No downloads yet",
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier
)
}
}
LazyVerticalGrid(
columns = GridCells.Adaptive(minSize = 120.dp),
contentPadding = PaddingValues(16.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp),
modifier = modifier.background(MaterialTheme.colorScheme.background)
) {
items(downloads.value) { item ->
PosterCard(
item = item,
onMovieSelected = viewModel::onMovieSelected,
onSeriesSelected = viewModel::onSeriesSelected,
onEpisodeSelected = { _, _, _ -> },
)
}
}
}

View File

@@ -20,7 +20,7 @@ import hu.bbara.purefin.core.data.room.entity.SeriesEntity
SeasonEntity::class,
EpisodeEntity::class,
],
version = 4,
version = 5,
exportSchema = false
)
@TypeConverters(UuidConverters::class)

View File

@@ -0,0 +1,60 @@
package hu.bbara.purefin.feature.shared.download
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import hu.bbara.purefin.core.data.OfflineMediaRepository
import hu.bbara.purefin.core.data.navigation.MovieDto
import hu.bbara.purefin.core.data.navigation.NavigationManager
import hu.bbara.purefin.core.data.navigation.Route
import hu.bbara.purefin.core.data.navigation.SeriesDto
import hu.bbara.purefin.feature.download.MediaDownloadManager
import hu.bbara.purefin.feature.shared.home.PosterItem
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
import org.jellyfin.sdk.model.UUID
import org.jellyfin.sdk.model.api.BaseItemKind
import javax.inject.Inject
@HiltViewModel
class DownloadsViewModel @Inject constructor(
private val offlineMediaRepository: OfflineMediaRepository,
private val navigationManager: NavigationManager,
private val downloadManager: MediaDownloadManager
) : ViewModel() {
fun onMovieSelected(movieId: UUID) {
navigationManager.navigate(Route.MovieRoute(
MovieDto(
id = movieId,
)
))
}
fun onSeriesSelected(seriesId: UUID) {
viewModelScope.launch {
navigationManager.navigate(Route.SeriesRoute(
SeriesDto(
id = seriesId,
)
))
}
}
val downloads = combine(
offlineMediaRepository.movies,
offlineMediaRepository.series
) { movies, series ->
movies.values.map {
PosterItem(
type = BaseItemKind.MOVIE,
movie = it
)
} + series.values.map {
PosterItem(
type = BaseItemKind.SERIES,
series = it
)
}
}
}