refactor: extract core-model into its own module

This commit is contained in:
2026-04-24 18:11:28 +02:00
parent ab7700d202
commit 354314710b
23 changed files with 145 additions and 145 deletions

View File

@@ -10,7 +10,6 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.withFrameNanos import androidx.compose.runtime.withFrameNanos
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester

View File

@@ -20,7 +20,6 @@ import androidx.compose.foundation.layout.sizeIn
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape

View File

@@ -52,6 +52,8 @@ kotlin {
dependencies { dependencies {
implementation(project(":data")) implementation(project(":data"))
implementation(project(":core")) implementation(project(":core"))
//TODO: temporary hack fix it
implementation(project(":core-model"))
implementation(project(":core-ui")) implementation(project(":core-ui"))
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.lifecycle.runtime.ktx)

View File

@@ -34,17 +34,16 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import hu.bbara.purefin.ui.common.media.MediaCastRow
import hu.bbara.purefin.ui.common.media.MediaSynopsis
import hu.bbara.purefin.ui.common.media.mediaPlaybackProgress
import hu.bbara.purefin.ui.common.media.mediaPlayButtonText
import hu.bbara.purefin.ui.common.button.GhostIconButton
import hu.bbara.purefin.ui.common.button.MediaActionButton
import hu.bbara.purefin.ui.common.media.MediaPlaybackSettings
import hu.bbara.purefin.ui.common.button.MediaResumeButton
import hu.bbara.purefin.download.DownloadState import hu.bbara.purefin.download.DownloadState
import hu.bbara.purefin.model.Episode import hu.bbara.purefin.model.Episode
import hu.bbara.purefin.player.PlayerActivity import hu.bbara.purefin.player.PlayerActivity
import hu.bbara.purefin.ui.common.button.GhostIconButton
import hu.bbara.purefin.ui.common.button.MediaActionButton
import hu.bbara.purefin.ui.common.button.MediaResumeButton
import hu.bbara.purefin.ui.common.media.MediaPlaybackSettings
import hu.bbara.purefin.ui.common.media.MediaSynopsis
import hu.bbara.purefin.ui.common.media.mediaPlayButtonText
import hu.bbara.purefin.ui.common.media.mediaPlaybackProgress
internal sealed interface EpisodeTopBarShortcut { internal sealed interface EpisodeTopBarShortcut {
val label: String val label: String
@@ -182,9 +181,10 @@ internal fun EpisodeDetails(
fontWeight = FontWeight.Bold fontWeight = FontWeight.Bold
) )
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(12.dp))
MediaCastRow( //TODO use it
cast = episode.cast // MediaCastRow(
) // cast = episode.cast
// )
} }
} }
} }

View File

@@ -29,17 +29,16 @@ import androidx.compose.ui.platform.LocalContext
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
import hu.bbara.purefin.ui.common.media.MediaCastRow
import hu.bbara.purefin.ui.common.media.MediaSynopsis
import hu.bbara.purefin.ui.common.media.mediaPlaybackProgress
import hu.bbara.purefin.ui.common.media.mediaPlayButtonText
import hu.bbara.purefin.ui.common.button.GhostIconButton
import hu.bbara.purefin.ui.common.button.MediaActionButton
import hu.bbara.purefin.ui.common.media.MediaPlaybackSettings
import hu.bbara.purefin.ui.common.button.MediaResumeButton
import hu.bbara.purefin.download.DownloadState import hu.bbara.purefin.download.DownloadState
import hu.bbara.purefin.model.Movie import hu.bbara.purefin.model.Movie
import hu.bbara.purefin.player.PlayerActivity import hu.bbara.purefin.player.PlayerActivity
import hu.bbara.purefin.ui.common.button.GhostIconButton
import hu.bbara.purefin.ui.common.button.MediaActionButton
import hu.bbara.purefin.ui.common.button.MediaResumeButton
import hu.bbara.purefin.ui.common.media.MediaPlaybackSettings
import hu.bbara.purefin.ui.common.media.MediaSynopsis
import hu.bbara.purefin.ui.common.media.mediaPlayButtonText
import hu.bbara.purefin.ui.common.media.mediaPlaybackProgress
@Composable @Composable
internal fun MovieTopBar( internal fun MovieTopBar(
@@ -139,9 +138,10 @@ internal fun MovieDetails(
fontWeight = FontWeight.Bold fontWeight = FontWeight.Bold
) )
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(12.dp))
MediaCastRow( //TODO fix
cast = movie.cast, // MediaCastRow(
) // cast = movie.cast,
// )
} }
} }
} }

View File

@@ -1,5 +1,7 @@
package hu.bbara.purefin.ui.screen.series package hu.bbara.purefin.ui.screen.series
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@@ -15,32 +17,30 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import hu.bbara.purefin.ui.common.media.MediaSynopsis
import hu.bbara.purefin.ui.screen.waiting.PurefinWaitingScreen
import hu.bbara.purefin.ui.common.media.MediaHero
import hu.bbara.purefin.download.DownloadState import hu.bbara.purefin.download.DownloadState
import hu.bbara.purefin.feature.content.series.SeriesViewModel
import hu.bbara.purefin.image.ArtworkKind
import hu.bbara.purefin.image.ImageUrlBuilder import hu.bbara.purefin.image.ImageUrlBuilder
import hu.bbara.purefin.navigation.SeriesDto
import hu.bbara.purefin.model.CastMember import hu.bbara.purefin.model.CastMember
import hu.bbara.purefin.model.Episode import hu.bbara.purefin.model.Episode
import hu.bbara.purefin.model.Season import hu.bbara.purefin.model.Season
import hu.bbara.purefin.model.Series import hu.bbara.purefin.model.Series
import hu.bbara.purefin.feature.content.series.SeriesViewModel import hu.bbara.purefin.navigation.SeriesDto
import hu.bbara.purefin.ui.common.media.MediaHero
import hu.bbara.purefin.ui.common.media.MediaSynopsis
import hu.bbara.purefin.ui.screen.series.components.CastRow import hu.bbara.purefin.ui.screen.series.components.CastRow
import hu.bbara.purefin.ui.screen.series.components.EpisodeCarousel import hu.bbara.purefin.ui.screen.series.components.EpisodeCarousel
import hu.bbara.purefin.ui.screen.series.components.SeasonTabs import hu.bbara.purefin.ui.screen.series.components.SeasonTabs
@@ -48,8 +48,8 @@ import hu.bbara.purefin.ui.screen.series.components.SeriesActionButtons
import hu.bbara.purefin.ui.screen.series.components.SeriesDownloadOption import hu.bbara.purefin.ui.screen.series.components.SeriesDownloadOption
import hu.bbara.purefin.ui.screen.series.components.SeriesMetaChips import hu.bbara.purefin.ui.screen.series.components.SeriesMetaChips
import hu.bbara.purefin.ui.screen.series.components.SeriesTopBar import hu.bbara.purefin.ui.screen.series.components.SeriesTopBar
import hu.bbara.purefin.ui.screen.waiting.PurefinWaitingScreen
import hu.bbara.purefin.ui.theme.AppTheme import hu.bbara.purefin.ui.theme.AppTheme
import hu.bbara.purefin.image.ArtworkKind
import java.util.UUID import java.util.UUID
@Composable @Composable

View File

@@ -55,28 +55,27 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import hu.bbara.purefin.ui.common.media.MediaCastRow
import hu.bbara.purefin.ui.common.media.MediaMetadataFlowRow
import hu.bbara.purefin.ui.common.media.mediaPlaybackProgress
import hu.bbara.purefin.ui.common.media.mediaPlayButtonText
import hu.bbara.purefin.ui.common.button.GhostIconButton
import hu.bbara.purefin.ui.common.button.MediaActionButton
import hu.bbara.purefin.ui.common.bar.MediaProgressBar
import hu.bbara.purefin.ui.common.button.MediaResumeButton
import hu.bbara.purefin.ui.common.image.PurefinAsyncImage
import hu.bbara.purefin.ui.common.badge.WatchStateBadge
import hu.bbara.purefin.download.DownloadState import hu.bbara.purefin.download.DownloadState
import hu.bbara.purefin.feature.content.series.SeriesViewModel
import hu.bbara.purefin.image.ArtworkKind
import hu.bbara.purefin.image.ImageUrlBuilder import hu.bbara.purefin.image.ImageUrlBuilder
import hu.bbara.purefin.navigation.EpisodeDto
import hu.bbara.purefin.navigation.LocalNavigationManager
import hu.bbara.purefin.navigation.Route
import hu.bbara.purefin.model.CastMember import hu.bbara.purefin.model.CastMember
import hu.bbara.purefin.model.Episode import hu.bbara.purefin.model.Episode
import hu.bbara.purefin.model.Season import hu.bbara.purefin.model.Season
import hu.bbara.purefin.model.Series import hu.bbara.purefin.model.Series
import hu.bbara.purefin.feature.content.series.SeriesViewModel import hu.bbara.purefin.navigation.EpisodeDto
import hu.bbara.purefin.navigation.LocalNavigationManager
import hu.bbara.purefin.navigation.Route
import hu.bbara.purefin.player.PlayerActivity import hu.bbara.purefin.player.PlayerActivity
import hu.bbara.purefin.image.ArtworkKind import hu.bbara.purefin.ui.common.badge.WatchStateBadge
import hu.bbara.purefin.ui.common.bar.MediaProgressBar
import hu.bbara.purefin.ui.common.button.GhostIconButton
import hu.bbara.purefin.ui.common.button.MediaActionButton
import hu.bbara.purefin.ui.common.button.MediaResumeButton
import hu.bbara.purefin.ui.common.image.PurefinAsyncImage
import hu.bbara.purefin.ui.common.media.MediaMetadataFlowRow
import hu.bbara.purefin.ui.common.media.mediaPlayButtonText
import hu.bbara.purefin.ui.common.media.mediaPlaybackProgress
@Composable @Composable
internal fun SeriesTopBar( internal fun SeriesTopBar(
@@ -407,11 +406,12 @@ private fun EpisodeCard(
@Composable @Composable
internal fun CastRow(cast: List<CastMember>, modifier: Modifier = Modifier) { internal fun CastRow(cast: List<CastMember>, modifier: Modifier = Modifier) {
MediaCastRow( //TODO fix
cast = cast, // MediaCastRow(
modifier = modifier, // cast = cast,
cardWidth = 84.dp, // modifier = modifier,
nameSize = 11.sp, // cardWidth = 84.dp,
roleSize = 10.sp // nameSize = 11.sp,
) // roleSize = 10.sp
// )
} }

1
core-model/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,13 @@
plugins {
id("java-library")
alias(libs.plugins.kotlin.jvm)
}
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlin {
compilerOptions {
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11
}
}

View File

@@ -2,23 +2,11 @@ package hu.bbara.purefin.ui.common.media
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Person
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -26,15 +14,9 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import hu.bbara.purefin.model.CastMember
import hu.bbara.purefin.ui.common.image.PurefinAsyncImage
@Composable @Composable
fun MediaMetaChip( fun MediaMetaChip(
@@ -63,73 +45,74 @@ fun MediaMetaChip(
} }
} }
@Composable //TODO use CastMemberUiModel
fun MediaCastRow( //@Composable
cast: List<CastMember>, //fun MediaCastRow(
modifier: Modifier = Modifier, // cast: List<CastMember>,
cardWidth: Dp = 96.dp, // modifier: Modifier = Modifier,
nameSize: TextUnit = 12.sp, // cardWidth: Dp = 96.dp,
roleSize: TextUnit = 10.sp // nameSize: TextUnit = 12.sp,
) { // roleSize: TextUnit = 10.sp
val scheme = MaterialTheme.colorScheme //) {
val mutedStrong = scheme.onSurfaceVariant.copy(alpha = 0.7f) // val scheme = MaterialTheme.colorScheme
// val mutedStrong = scheme.onSurfaceVariant.copy(alpha = 0.7f)
LazyRow( //
modifier = modifier, // LazyRow(
contentPadding = PaddingValues(horizontal = 4.dp), // modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(16.dp) // contentPadding = PaddingValues(horizontal = 4.dp),
) { // horizontalArrangement = Arrangement.spacedBy(16.dp)
items( // ) {
items = cast, // items(
key = { member -> "${member.name}:${member.role}:${member.imageUrl.orEmpty()}" } // items = cast,
) { member -> // key = { member -> "${member.name}:${member.role}:${member.imageUrl.orEmpty()}" }
Column(modifier = Modifier.width(cardWidth)) { // ) { member ->
Box( // Column(modifier = Modifier.width(cardWidth)) {
modifier = Modifier // Box(
.aspectRatio(4f / 5f) // modifier = Modifier
.clip(RoundedCornerShape(12.dp)) // .aspectRatio(4f / 5f)
.background(scheme.surfaceVariant) // .clip(RoundedCornerShape(12.dp))
) { // .background(scheme.surfaceVariant)
if (member.imageUrl == null) { // ) {
Box( // if (member.imageUrl == null) {
modifier = Modifier // Box(
.fillMaxSize() // modifier = Modifier
.background(scheme.surfaceVariant.copy(alpha = 0.6f)), // .fillMaxSize()
contentAlignment = Alignment.Center // .background(scheme.surfaceVariant.copy(alpha = 0.6f)),
) { // contentAlignment = Alignment.Center
Icon( // ) {
imageVector = Icons.Outlined.Person, // Icon(
contentDescription = null, // imageVector = Icons.Outlined.Person,
tint = mutedStrong // contentDescription = null,
) // tint = mutedStrong
} // )
} else { // }
PurefinAsyncImage( // } else {
model = member.imageUrl, // PurefinAsyncImage(
contentDescription = null, // model = member.imageUrl,
modifier = Modifier.fillMaxSize(), // contentDescription = null,
contentScale = ContentScale.Crop, // modifier = Modifier.fillMaxSize(),
fallbackIcon = null // contentScale = ContentScale.Crop,
) // fallbackIcon = null
} // )
} // }
Spacer(modifier = Modifier.height(6.dp)) // }
Text( // Spacer(modifier = Modifier.height(6.dp))
text = member.name, // Text(
color = scheme.onBackground, // text = member.name,
fontSize = nameSize, // color = scheme.onBackground,
fontWeight = FontWeight.Bold, // fontSize = nameSize,
maxLines = 1, // fontWeight = FontWeight.Bold,
overflow = TextOverflow.Ellipsis // maxLines = 1,
) // overflow = TextOverflow.Ellipsis
Text( // )
text = member.role, // Text(
color = mutedStrong, // text = member.role,
fontSize = roleSize, // color = mutedStrong,
maxLines = 1, // fontSize = roleSize,
overflow = TextOverflow.Ellipsis // maxLines = 1,
) // overflow = TextOverflow.Ellipsis
} // )
} // }
} // }
} // }
//}

View File

@@ -30,6 +30,7 @@ kotlin {
dependencies { dependencies {
implementation(project(":data")) implementation(project(":data"))
implementation(project(":core-model"))
implementation(libs.hilt) implementation(libs.hilt)
ksp(libs.hilt.compiler) ksp(libs.hilt.compiler)
implementation(libs.androidx.lifecycle.viewmodel.ktx) implementation(libs.androidx.lifecycle.viewmodel.ktx)

View File

@@ -29,6 +29,7 @@ kotlin {
} }
dependencies { dependencies {
implementation(project(":core-model"))
implementation(libs.media3.common) implementation(libs.media3.common)
implementation(libs.kotlinx.coroutines.core) implementation(libs.kotlinx.coroutines.core)
implementation(libs.jellyfin.core) implementation(libs.jellyfin.core)

View File

@@ -28,3 +28,4 @@ include(":app-tv")
include(":data") include(":data")
include(":core") include(":core")
include(":core-ui") include(":core-ui")
include(":core-model")