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.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.withFrameNanos
import androidx.compose.ui.Modifier
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.widthIn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape

View File

@@ -52,6 +52,8 @@ kotlin {
dependencies {
implementation(project(":data"))
implementation(project(":core"))
//TODO: temporary hack fix it
implementation(project(":core-model"))
implementation(project(":core-ui"))
implementation(libs.androidx.core.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.unit.dp
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.model.Episode
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 {
val label: String
@@ -182,9 +181,10 @@ internal fun EpisodeDetails(
fontWeight = FontWeight.Bold
)
Spacer(modifier = Modifier.height(12.dp))
MediaCastRow(
cast = episode.cast
)
//TODO use it
// 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.unit.dp
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.model.Movie
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
internal fun MovieTopBar(
@@ -139,9 +138,10 @@ internal fun MovieDetails(
fontWeight = FontWeight.Bold
)
Spacer(modifier = Modifier.height(12.dp))
MediaCastRow(
cast = movie.cast,
)
//TODO fix
// MediaCastRow(
// cast = movie.cast,
// )
}
}
}

View File

@@ -1,5 +1,7 @@
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.Spacer
import androidx.compose.foundation.layout.fillMaxSize
@@ -15,32 +17,30 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
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.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalConfiguration
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.sp
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.feature.content.series.SeriesViewModel
import hu.bbara.purefin.image.ArtworkKind
import hu.bbara.purefin.image.ImageUrlBuilder
import hu.bbara.purefin.navigation.SeriesDto
import hu.bbara.purefin.model.CastMember
import hu.bbara.purefin.model.Episode
import hu.bbara.purefin.model.Season
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.EpisodeCarousel
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.SeriesMetaChips
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.image.ArtworkKind
import java.util.UUID
@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.sp
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.feature.content.series.SeriesViewModel
import hu.bbara.purefin.image.ArtworkKind
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.Episode
import hu.bbara.purefin.model.Season
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.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
internal fun SeriesTopBar(
@@ -407,11 +406,12 @@ private fun EpisodeCard(
@Composable
internal fun CastRow(cast: List<CastMember>, modifier: Modifier = Modifier) {
MediaCastRow(
cast = cast,
modifier = modifier,
cardWidth = 84.dp,
nameSize = 11.sp,
roleSize = 10.sp
)
//TODO fix
// MediaCastRow(
// cast = cast,
// modifier = modifier,
// cardWidth = 84.dp,
// 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.border
import androidx.compose.foundation.layout.Arrangement
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.padding
import androidx.compose.foundation.layout.width
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.material.icons.Icons
import androidx.compose.material.icons.outlined.Person
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -26,15 +14,9 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
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.sp
import hu.bbara.purefin.model.CastMember
import hu.bbara.purefin.ui.common.image.PurefinAsyncImage
@Composable
fun MediaMetaChip(
@@ -63,73 +45,74 @@ fun MediaMetaChip(
}
}
@Composable
fun MediaCastRow(
cast: List<CastMember>,
modifier: Modifier = Modifier,
cardWidth: Dp = 96.dp,
nameSize: TextUnit = 12.sp,
roleSize: TextUnit = 10.sp
) {
val scheme = MaterialTheme.colorScheme
val mutedStrong = scheme.onSurfaceVariant.copy(alpha = 0.7f)
LazyRow(
modifier = modifier,
contentPadding = PaddingValues(horizontal = 4.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
items(
items = cast,
key = { member -> "${member.name}:${member.role}:${member.imageUrl.orEmpty()}" }
) { member ->
Column(modifier = Modifier.width(cardWidth)) {
Box(
modifier = Modifier
.aspectRatio(4f / 5f)
.clip(RoundedCornerShape(12.dp))
.background(scheme.surfaceVariant)
) {
if (member.imageUrl == null) {
Box(
modifier = Modifier
.fillMaxSize()
.background(scheme.surfaceVariant.copy(alpha = 0.6f)),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = Icons.Outlined.Person,
contentDescription = null,
tint = mutedStrong
)
}
} else {
PurefinAsyncImage(
model = member.imageUrl,
contentDescription = null,
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop,
fallbackIcon = null
)
}
}
Spacer(modifier = Modifier.height(6.dp))
Text(
text = member.name,
color = scheme.onBackground,
fontSize = nameSize,
fontWeight = FontWeight.Bold,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Text(
text = member.role,
color = mutedStrong,
fontSize = roleSize,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
}
}
}
//TODO use CastMemberUiModel
//@Composable
//fun MediaCastRow(
// cast: List<CastMember>,
// modifier: Modifier = Modifier,
// cardWidth: Dp = 96.dp,
// nameSize: TextUnit = 12.sp,
// roleSize: TextUnit = 10.sp
//) {
// val scheme = MaterialTheme.colorScheme
// val mutedStrong = scheme.onSurfaceVariant.copy(alpha = 0.7f)
//
// LazyRow(
// modifier = modifier,
// contentPadding = PaddingValues(horizontal = 4.dp),
// horizontalArrangement = Arrangement.spacedBy(16.dp)
// ) {
// items(
// items = cast,
// key = { member -> "${member.name}:${member.role}:${member.imageUrl.orEmpty()}" }
// ) { member ->
// Column(modifier = Modifier.width(cardWidth)) {
// Box(
// modifier = Modifier
// .aspectRatio(4f / 5f)
// .clip(RoundedCornerShape(12.dp))
// .background(scheme.surfaceVariant)
// ) {
// if (member.imageUrl == null) {
// Box(
// modifier = Modifier
// .fillMaxSize()
// .background(scheme.surfaceVariant.copy(alpha = 0.6f)),
// contentAlignment = Alignment.Center
// ) {
// Icon(
// imageVector = Icons.Outlined.Person,
// contentDescription = null,
// tint = mutedStrong
// )
// }
// } else {
// PurefinAsyncImage(
// model = member.imageUrl,
// contentDescription = null,
// modifier = Modifier.fillMaxSize(),
// contentScale = ContentScale.Crop,
// fallbackIcon = null
// )
// }
// }
// Spacer(modifier = Modifier.height(6.dp))
// Text(
// text = member.name,
// color = scheme.onBackground,
// fontSize = nameSize,
// fontWeight = FontWeight.Bold,
// maxLines = 1,
// overflow = TextOverflow.Ellipsis
// )
// Text(
// text = member.role,
// color = mutedStrong,
// fontSize = roleSize,
// maxLines = 1,
// overflow = TextOverflow.Ellipsis
// )
// }
// }
// }
//}

View File

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

View File

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

View File

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