mirror of
https://github.com/bbara04/Purefin.git
synced 2026-03-31 17:10:08 +02:00
Add screen previews
This commit is contained in:
@@ -4,6 +4,7 @@ import android.Manifest
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
@@ -26,8 +27,11 @@ import hu.bbara.purefin.core.data.navigation.LocalNavigationBackStack
|
|||||||
import hu.bbara.purefin.core.data.navigation.LocalNavigationManager
|
import hu.bbara.purefin.core.data.navigation.LocalNavigationManager
|
||||||
import hu.bbara.purefin.core.data.navigation.Route
|
import hu.bbara.purefin.core.data.navigation.Route
|
||||||
import hu.bbara.purefin.core.model.Episode
|
import hu.bbara.purefin.core.model.Episode
|
||||||
|
import hu.bbara.purefin.core.model.CastMember
|
||||||
import hu.bbara.purefin.feature.download.DownloadState
|
import hu.bbara.purefin.feature.download.DownloadState
|
||||||
import hu.bbara.purefin.feature.shared.content.episode.EpisodeScreenViewModel
|
import hu.bbara.purefin.feature.shared.content.episode.EpisodeScreenViewModel
|
||||||
|
import hu.bbara.purefin.ui.theme.AppTheme
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun EpisodeScreen(
|
fun EpisodeScreen(
|
||||||
@@ -142,4 +146,43 @@ private fun EpisodeScreenInternal(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Preview(showBackground = true)
|
||||||
|
@Composable
|
||||||
|
private fun EpisodeScreenPreview() {
|
||||||
|
AppTheme {
|
||||||
|
EpisodeScreenInternal(
|
||||||
|
episode = previewEpisode(),
|
||||||
|
seriesTitle = "Severance",
|
||||||
|
topBarShortcut = EpisodeTopBarShortcut.Series(onClick = {}),
|
||||||
|
downloadState = DownloadState.Downloading(progressPercent = 0.42f),
|
||||||
|
onBack = {},
|
||||||
|
onSeriesClick = {},
|
||||||
|
onDownloadClick = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun previewEpisode(): Episode {
|
||||||
|
val seriesId = UUID.fromString("11111111-1111-1111-1111-111111111111")
|
||||||
|
val seasonId = UUID.fromString("22222222-2222-2222-2222-222222222222")
|
||||||
|
return Episode(
|
||||||
|
id = UUID.fromString("33333333-3333-3333-3333-333333333333"),
|
||||||
|
seriesId = seriesId,
|
||||||
|
seasonId = seasonId,
|
||||||
|
index = 4,
|
||||||
|
title = "The You You Are",
|
||||||
|
synopsis = "Mark is pulled deeper into Lumon's fractured world as the team chases a clue that reframes everything they thought they understood.",
|
||||||
|
releaseDate = "2025",
|
||||||
|
rating = "16+",
|
||||||
|
runtime = "49m",
|
||||||
|
progress = 63.0,
|
||||||
|
watched = false,
|
||||||
|
format = "4K",
|
||||||
|
heroImageUrl = "https://images.unsplash.com/photo-1500530855697-b586d89ba3ee",
|
||||||
|
cast = listOf(
|
||||||
|
CastMember("Adam Scott", "Mark Scout", null),
|
||||||
|
CastMember("Britt Lower", "Helly R.", null),
|
||||||
|
CastMember("John Turturro", "Irving B.", null)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import android.Manifest
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
@@ -21,9 +22,12 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
|||||||
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
|
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
|
||||||
import hu.bbara.purefin.common.ui.components.MediaHero
|
import hu.bbara.purefin.common.ui.components.MediaHero
|
||||||
import hu.bbara.purefin.core.data.navigation.MovieDto
|
import hu.bbara.purefin.core.data.navigation.MovieDto
|
||||||
|
import hu.bbara.purefin.core.model.CastMember
|
||||||
import hu.bbara.purefin.core.model.Movie
|
import hu.bbara.purefin.core.model.Movie
|
||||||
import hu.bbara.purefin.feature.download.DownloadState
|
import hu.bbara.purefin.feature.download.DownloadState
|
||||||
import hu.bbara.purefin.feature.shared.content.movie.MovieScreenViewModel
|
import hu.bbara.purefin.feature.shared.content.movie.MovieScreenViewModel
|
||||||
|
import hu.bbara.purefin.ui.theme.AppTheme
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MovieScreen(
|
fun MovieScreen(
|
||||||
@@ -107,3 +111,38 @@ private fun MovieScreenInternal(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Preview(showBackground = true)
|
||||||
|
@Composable
|
||||||
|
private fun MovieScreenPreview() {
|
||||||
|
AppTheme {
|
||||||
|
MovieScreenInternal(
|
||||||
|
movie = previewMovie(),
|
||||||
|
downloadState = DownloadState.NotDownloaded,
|
||||||
|
onDownloadClick = {},
|
||||||
|
onBack = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun previewMovie(): Movie =
|
||||||
|
Movie(
|
||||||
|
id = UUID.fromString("44444444-4444-4444-4444-444444444444"),
|
||||||
|
libraryId = UUID.fromString("55555555-5555-5555-5555-555555555555"),
|
||||||
|
title = "Blade Runner 2049",
|
||||||
|
progress = 18.0,
|
||||||
|
watched = false,
|
||||||
|
year = "2017",
|
||||||
|
rating = "16+",
|
||||||
|
runtime = "2h 44m",
|
||||||
|
format = "Dolby Vision",
|
||||||
|
synopsis = "A new blade runner uncovers a buried secret that forces him to trace the vanished footsteps of Rick Deckard.",
|
||||||
|
heroImageUrl = "https://images.unsplash.com/photo-1519608487953-e999c86e7455",
|
||||||
|
audioTrack = "English 5.1",
|
||||||
|
subtitles = "English CC",
|
||||||
|
cast = listOf(
|
||||||
|
CastMember("Ryan Gosling", "K", null),
|
||||||
|
CastMember("Ana de Armas", "Joi", null),
|
||||||
|
CastMember("Harrison Ford", "Rick Deckard", null)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
@@ -27,10 +28,14 @@ import hu.bbara.purefin.common.ui.MediaSynopsis
|
|||||||
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
|
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
|
||||||
import hu.bbara.purefin.common.ui.components.MediaHero
|
import hu.bbara.purefin.common.ui.components.MediaHero
|
||||||
import hu.bbara.purefin.core.data.navigation.SeriesDto
|
import hu.bbara.purefin.core.data.navigation.SeriesDto
|
||||||
|
import hu.bbara.purefin.core.model.CastMember
|
||||||
|
import hu.bbara.purefin.core.model.Episode
|
||||||
import hu.bbara.purefin.core.model.Season
|
import hu.bbara.purefin.core.model.Season
|
||||||
import hu.bbara.purefin.core.model.Series
|
import hu.bbara.purefin.core.model.Series
|
||||||
import hu.bbara.purefin.feature.download.DownloadState
|
import hu.bbara.purefin.feature.download.DownloadState
|
||||||
import hu.bbara.purefin.feature.shared.content.series.SeriesViewModel
|
import hu.bbara.purefin.feature.shared.content.series.SeriesViewModel
|
||||||
|
import hu.bbara.purefin.ui.theme.AppTheme
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SeriesScreen(
|
fun SeriesScreen(
|
||||||
@@ -51,7 +56,19 @@ fun SeriesScreen(
|
|||||||
}
|
}
|
||||||
SeriesScreenInternal(
|
SeriesScreenInternal(
|
||||||
series = seriesData,
|
series = seriesData,
|
||||||
viewModel = viewModel,
|
seriesDownloadState = viewModel.seriesDownloadState.collectAsState().value,
|
||||||
|
seasonDownloadState = viewModel.seasonDownloadState.collectAsState().value,
|
||||||
|
onDownloadOptionSelected = { option, selectedSeason ->
|
||||||
|
when (option) {
|
||||||
|
SeriesDownloadOption.SEASON ->
|
||||||
|
viewModel.downloadSeason(selectedSeason.episodes)
|
||||||
|
SeriesDownloadOption.SERIES ->
|
||||||
|
viewModel.downloadSeries(seriesData)
|
||||||
|
SeriesDownloadOption.SMART ->
|
||||||
|
viewModel.enableSmartDownload(seriesData.id)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onObserveSeasonDownloadState = viewModel::observeSeasonDownloadState,
|
||||||
onBack = viewModel::onBack,
|
onBack = viewModel::onBack,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
@@ -63,7 +80,10 @@ fun SeriesScreen(
|
|||||||
@Composable
|
@Composable
|
||||||
private fun SeriesScreenInternal(
|
private fun SeriesScreenInternal(
|
||||||
series: Series,
|
series: Series,
|
||||||
viewModel: SeriesViewModel,
|
seriesDownloadState: DownloadState,
|
||||||
|
seasonDownloadState: DownloadState,
|
||||||
|
onDownloadOptionSelected: (SeriesDownloadOption, Season) -> Unit,
|
||||||
|
onObserveSeasonDownloadState: (List<Episode>) -> Unit,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
@@ -89,10 +109,8 @@ private fun SeriesScreenInternal(
|
|||||||
} ?: series.seasons.firstOrNull()?.episodes?.firstOrNull()
|
} ?: series.seasons.firstOrNull()?.episodes?.firstOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
val seriesDownloadState by viewModel.seriesDownloadState.collectAsState()
|
|
||||||
val seasonDownloadState by viewModel.seasonDownloadState.collectAsState()
|
|
||||||
LaunchedEffect(selectedSeason.id, selectedSeason.episodes) {
|
LaunchedEffect(selectedSeason.id, selectedSeason.episodes) {
|
||||||
viewModel.observeSeasonDownloadState(selectedSeason.episodes)
|
onObserveSeasonDownloadState(selectedSeason.episodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
@@ -138,14 +156,7 @@ private fun SeriesScreenInternal(
|
|||||||
selectedSeason = selectedSeason,
|
selectedSeason = selectedSeason,
|
||||||
seasonDownloadState = seasonDownloadState,
|
seasonDownloadState = seasonDownloadState,
|
||||||
onDownloadOptionSelected = { option ->
|
onDownloadOptionSelected = { option ->
|
||||||
when (option) {
|
onDownloadOptionSelected(option, selectedSeason)
|
||||||
SeriesDownloadOption.SEASON ->
|
|
||||||
viewModel.downloadSeason(selectedSeason.episodes)
|
|
||||||
SeriesDownloadOption.SERIES ->
|
|
||||||
viewModel.downloadSeries(series)
|
|
||||||
SeriesDownloadOption.SMART ->
|
|
||||||
viewModel.enableSmartDownload(series.id)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
@@ -180,3 +191,114 @@ private fun SeriesScreenInternal(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Preview(showBackground = true)
|
||||||
|
@Composable
|
||||||
|
private fun SeriesScreenPreview() {
|
||||||
|
AppTheme {
|
||||||
|
SeriesScreenInternal(
|
||||||
|
series = previewSeries(),
|
||||||
|
seriesDownloadState = DownloadState.Downloading(progressPercent = 0.58f),
|
||||||
|
seasonDownloadState = DownloadState.NotDownloaded,
|
||||||
|
onDownloadOptionSelected = { _, _ -> },
|
||||||
|
onObserveSeasonDownloadState = {},
|
||||||
|
onBack = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun previewSeries(): Series {
|
||||||
|
val libraryId = UUID.fromString("66666666-6666-6666-6666-666666666666")
|
||||||
|
val seriesId = UUID.fromString("77777777-7777-7777-7777-777777777777")
|
||||||
|
val seasonOneId = UUID.fromString("88888888-8888-8888-8888-888888888888")
|
||||||
|
val seasonTwoId = UUID.fromString("99999999-9999-9999-9999-999999999999")
|
||||||
|
|
||||||
|
val seasonOneEpisodes = listOf(
|
||||||
|
Episode(
|
||||||
|
id = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa1"),
|
||||||
|
seriesId = seriesId,
|
||||||
|
seasonId = seasonOneId,
|
||||||
|
index = 1,
|
||||||
|
title = "A Fresh Start",
|
||||||
|
synopsis = "A fractured crew tries to reassemble after a year apart.",
|
||||||
|
releaseDate = "2024",
|
||||||
|
rating = "16+",
|
||||||
|
runtime = "51m",
|
||||||
|
progress = 100.0,
|
||||||
|
watched = true,
|
||||||
|
format = "4K",
|
||||||
|
heroImageUrl = "https://images.unsplash.com/photo-1497032205916-ac775f0649ae",
|
||||||
|
cast = emptyList()
|
||||||
|
),
|
||||||
|
Episode(
|
||||||
|
id = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa2"),
|
||||||
|
seriesId = seriesId,
|
||||||
|
seasonId = seasonOneId,
|
||||||
|
index = 2,
|
||||||
|
title = "Signals",
|
||||||
|
synopsis = "Anomalies around the station point to a cover-up.",
|
||||||
|
releaseDate = "2024",
|
||||||
|
rating = "16+",
|
||||||
|
runtime = "48m",
|
||||||
|
progress = 34.0,
|
||||||
|
watched = false,
|
||||||
|
format = "4K",
|
||||||
|
heroImageUrl = "https://images.unsplash.com/photo-1520034475321-cbe63696469a",
|
||||||
|
cast = emptyList()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val seasonTwoEpisodes = listOf(
|
||||||
|
Episode(
|
||||||
|
id = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa3"),
|
||||||
|
seriesId = seriesId,
|
||||||
|
seasonId = seasonTwoId,
|
||||||
|
index = 1,
|
||||||
|
title = "Return Window",
|
||||||
|
synopsis = "A high-risk jump changes the rules of the mission.",
|
||||||
|
releaseDate = "2025",
|
||||||
|
rating = "16+",
|
||||||
|
runtime = "54m",
|
||||||
|
progress = null,
|
||||||
|
watched = false,
|
||||||
|
format = "4K",
|
||||||
|
heroImageUrl = "https://images.unsplash.com/photo-1500534314209-a25ddb2bd429",
|
||||||
|
cast = emptyList()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return Series(
|
||||||
|
id = seriesId,
|
||||||
|
libraryId = libraryId,
|
||||||
|
name = "Constellation",
|
||||||
|
synopsis = "When an experiment in orbit goes wrong, the survivors return home to a world that no longer fits their memories.",
|
||||||
|
year = "2024",
|
||||||
|
heroImageUrl = "https://images.unsplash.com/photo-1446776811953-b23d57bd21aa",
|
||||||
|
unwatchedEpisodeCount = 2,
|
||||||
|
seasonCount = 2,
|
||||||
|
seasons = listOf(
|
||||||
|
Season(
|
||||||
|
id = seasonOneId,
|
||||||
|
seriesId = seriesId,
|
||||||
|
name = "Season 1",
|
||||||
|
index = 1,
|
||||||
|
unwatchedEpisodeCount = 1,
|
||||||
|
episodeCount = seasonOneEpisodes.size,
|
||||||
|
episodes = seasonOneEpisodes
|
||||||
|
),
|
||||||
|
Season(
|
||||||
|
id = seasonTwoId,
|
||||||
|
seriesId = seriesId,
|
||||||
|
name = "Season 2",
|
||||||
|
index = 2,
|
||||||
|
unwatchedEpisodeCount = 1,
|
||||||
|
episodeCount = seasonTwoEpisodes.size,
|
||||||
|
episodes = seasonTwoEpisodes
|
||||||
|
)
|
||||||
|
),
|
||||||
|
cast = listOf(
|
||||||
|
CastMember("Noomi Rapace", "Jo", null),
|
||||||
|
CastMember("Jonathan Banks", "Henry", null),
|
||||||
|
CastMember("James D'Arcy", "Magnus", null)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user