refactor: modularize app into multi-module architecture

This commit is contained in:
2026-02-21 00:15:51 +01:00
parent 8601ef0236
commit 7333781f83
123 changed files with 668 additions and 404 deletions

2
.gitignore vendored
View File

@@ -9,7 +9,7 @@
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
**/build
/captures
.externalNativeBuild
.cxx

View File

@@ -47,6 +47,11 @@ kotlin {
}
dependencies {
implementation(project(":core:model"))
implementation(project(":core:data"))
implementation(project(":feature:download"))
implementation(project(":core:player"))
implementation(project(":feature:shared"))
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.lifecycle.viewmodel.compose)

View File

@@ -33,7 +33,7 @@
android:exported="false"
android:theme="@style/Theme.Purefin" />
<service
android:name=".download.PurefinDownloadService"
android:name="hu.bbara.purefin.feature.download.PurefinDownloadService"
android:exported="false"
android:foregroundServiceType="dataSync" />
</application>

View File

@@ -31,15 +31,15 @@ import coil3.network.okhttp.OkHttpNetworkFetcherFactory
import coil3.request.crossfade
import coil3.util.DebugLogger
import dagger.hilt.android.AndroidEntryPoint
import hu.bbara.purefin.client.JellyfinApiClient
import hu.bbara.purefin.client.JellyfinAuthInterceptor
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
import hu.bbara.purefin.core.data.client.JellyfinApiClient
import hu.bbara.purefin.core.data.client.JellyfinAuthInterceptor
import hu.bbara.purefin.core.data.navigation.LocalNavigationManager
import hu.bbara.purefin.core.data.navigation.NavigationCommand
import hu.bbara.purefin.core.data.navigation.NavigationManager
import hu.bbara.purefin.core.data.navigation.Route
import hu.bbara.purefin.core.data.session.UserSessionRepository
import hu.bbara.purefin.login.ui.LoginScreen
import hu.bbara.purefin.navigation.LocalNavigationManager
import hu.bbara.purefin.navigation.NavigationCommand
import hu.bbara.purefin.navigation.NavigationManager
import hu.bbara.purefin.navigation.Route
import hu.bbara.purefin.session.UserSessionRepository
import hu.bbara.purefin.ui.theme.AppTheme
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient

View File

@@ -1,14 +1,14 @@
package hu.bbara.purefin.app.content
import hu.bbara.purefin.app.content.episode.EpisodeUiModel
import hu.bbara.purefin.app.content.movie.MovieUiModel
import hu.bbara.purefin.app.content.series.SeriesCastMemberUiModel
import hu.bbara.purefin.app.content.series.SeriesEpisodeUiModel
import hu.bbara.purefin.app.content.series.SeriesSeasonUiModel
import hu.bbara.purefin.app.content.series.SeriesUiModel
import hu.bbara.purefin.feature.shared.content.episode.EpisodeUiModel
import hu.bbara.purefin.feature.shared.content.movie.MovieUiModel
import hu.bbara.purefin.feature.shared.content.series.SeriesCastMemberUiModel
import hu.bbara.purefin.feature.shared.content.series.SeriesEpisodeUiModel
import hu.bbara.purefin.feature.shared.content.series.SeriesSeasonUiModel
import hu.bbara.purefin.feature.shared.content.series.SeriesUiModel
import org.jellyfin.sdk.model.UUID
import hu.bbara.purefin.app.content.episode.CastMember as EpisodeCastMember
import hu.bbara.purefin.app.content.movie.CastMember as MovieCastMember
import hu.bbara.purefin.feature.shared.content.episode.CastMember as EpisodeCastMember
import hu.bbara.purefin.feature.shared.content.movie.CastMember as MovieCastMember
object ContentMockData {
fun series(): SeriesUiModel {

View File

@@ -37,7 +37,7 @@ import hu.bbara.purefin.common.ui.components.GhostIconButton
import hu.bbara.purefin.common.ui.components.MediaActionButton
import hu.bbara.purefin.common.ui.components.MediaPlaybackSettings
import hu.bbara.purefin.common.ui.components.MediaResumeButton
import hu.bbara.purefin.data.model.Episode
import hu.bbara.purefin.core.model.Episode
import hu.bbara.purefin.player.PlayerActivity
@Composable

View File

@@ -16,8 +16,9 @@ import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
import hu.bbara.purefin.common.ui.components.MediaHero
import hu.bbara.purefin.data.model.Episode
import hu.bbara.purefin.navigation.EpisodeDto
import hu.bbara.purefin.core.data.navigation.EpisodeDto
import hu.bbara.purefin.core.model.Episode
import hu.bbara.purefin.feature.shared.content.episode.EpisodeScreenViewModel
@Composable
fun EpisodeScreen(

View File

@@ -39,7 +39,8 @@ import hu.bbara.purefin.common.ui.components.GhostIconButton
import hu.bbara.purefin.common.ui.components.MediaActionButton
import hu.bbara.purefin.common.ui.components.MediaPlaybackSettings
import hu.bbara.purefin.common.ui.components.MediaResumeButton
import hu.bbara.purefin.download.DownloadState
import hu.bbara.purefin.feature.download.DownloadState
import hu.bbara.purefin.feature.shared.content.movie.MovieUiModel
import hu.bbara.purefin.player.PlayerActivity
@Composable

View File

@@ -22,8 +22,10 @@ import androidx.hilt.navigation.compose.hiltViewModel
import hu.bbara.purefin.app.content.ContentMockData
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
import hu.bbara.purefin.common.ui.components.MediaHero
import hu.bbara.purefin.download.DownloadState
import hu.bbara.purefin.navigation.MovieDto
import hu.bbara.purefin.core.data.navigation.MovieDto
import hu.bbara.purefin.feature.download.DownloadState
import hu.bbara.purefin.feature.shared.content.movie.MovieScreenViewModel
import hu.bbara.purefin.feature.shared.content.movie.MovieUiModel
@Composable
fun MovieScreen(

View File

@@ -53,10 +53,11 @@ import hu.bbara.purefin.common.ui.components.MediaActionButton
import hu.bbara.purefin.common.ui.components.MediaProgressBar
import hu.bbara.purefin.common.ui.components.PurefinAsyncImage
import hu.bbara.purefin.common.ui.components.WatchStateIndicator
import hu.bbara.purefin.data.model.CastMember
import hu.bbara.purefin.data.model.Episode
import hu.bbara.purefin.data.model.Season
import hu.bbara.purefin.data.model.Series
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.Series
import hu.bbara.purefin.feature.shared.content.series.SeriesViewModel
@Composable
internal fun SeriesTopBar(

View File

@@ -24,9 +24,10 @@ import androidx.hilt.navigation.compose.hiltViewModel
import hu.bbara.purefin.common.ui.MediaSynopsis
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
import hu.bbara.purefin.common.ui.components.MediaHero
import hu.bbara.purefin.data.model.Season
import hu.bbara.purefin.data.model.Series
import hu.bbara.purefin.navigation.SeriesDto
import hu.bbara.purefin.core.data.navigation.SeriesDto
import hu.bbara.purefin.core.model.Season
import hu.bbara.purefin.core.model.Series
import hu.bbara.purefin.feature.shared.content.series.SeriesViewModel
@Composable
fun SeriesScreen(

View File

@@ -1,7 +1,7 @@
package hu.bbara.purefin.app.home
import androidx.navigation3.runtime.EntryProviderScope
import hu.bbara.purefin.navigation.Route
import hu.bbara.purefin.core.data.navigation.Route
/**
* Navigation 3 entry definition for the Home section.

View File

@@ -25,6 +25,7 @@ import hu.bbara.purefin.app.home.ui.HomeDrawerContent
import hu.bbara.purefin.app.home.ui.HomeMockData
import hu.bbara.purefin.app.home.ui.HomeNavItem
import hu.bbara.purefin.app.home.ui.HomeTopBar
import hu.bbara.purefin.feature.shared.home.HomePageViewModel
import kotlinx.coroutines.launch
import org.jellyfin.sdk.model.api.CollectionType
@@ -74,7 +75,7 @@ fun HomePage(
primaryNavItems = libraryNavItems,
secondaryNavItems = HomeMockData.secondaryNavItems,
user = HomeMockData.user,
onLibrarySelected = viewModel::onLibrarySelected,
onLibrarySelected = { item -> viewModel.onLibrarySelected(item.id, item.label) },
onLogout = viewModel::logout
)
}

View File

@@ -10,6 +10,10 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import hu.bbara.purefin.feature.shared.home.ContinueWatchingItem
import hu.bbara.purefin.feature.shared.home.LibraryItem
import hu.bbara.purefin.feature.shared.home.NextUpItem
import hu.bbara.purefin.feature.shared.home.PosterItem
import org.jellyfin.sdk.model.UUID
@Composable

View File

@@ -1,85 +1,7 @@
package hu.bbara.purefin.app.home.ui
import androidx.compose.ui.graphics.vector.ImageVector
import hu.bbara.purefin.data.model.Episode
import hu.bbara.purefin.data.model.Movie
import hu.bbara.purefin.data.model.Series
import org.jellyfin.sdk.model.UUID
import org.jellyfin.sdk.model.api.BaseItemKind
import org.jellyfin.sdk.model.api.CollectionType
data class ContinueWatchingItem(
val type: BaseItemKind,
val movie: Movie? = null,
val episode: Episode? = null
) {
val id: UUID = when (type) {
BaseItemKind.MOVIE -> movie!!.id
BaseItemKind.EPISODE -> episode!!.id
else -> throw UnsupportedOperationException("Unsupported item type: $type")
}
val primaryText: String = when (type) {
BaseItemKind.MOVIE -> movie!!.title
BaseItemKind.EPISODE -> episode!!.title
else -> throw UnsupportedOperationException("Unsupported item type: $type")
}
val secondaryText: String = when (type) {
BaseItemKind.MOVIE -> movie!!.year
BaseItemKind.EPISODE -> episode!!.releaseDate
else -> throw UnsupportedOperationException("Unsupported item type: $type")
}
val progress: Double = when (type) {
BaseItemKind.MOVIE -> movie!!.progress ?: 0.0
BaseItemKind.EPISODE -> episode!!.progress ?: 0.0
else -> throw UnsupportedOperationException("Unsupported item type: $type")
}
}
data class NextUpItem(
val episode: Episode
) {
val id: UUID = episode.id
val primaryText: String = episode.title
val secondaryText: String = episode.releaseDate
}
data class LibraryItem(
val id: UUID,
val name: String,
val type: CollectionType,
val isEmpty: Boolean
)
data class PosterItem(
val type: BaseItemKind,
val movie: Movie? = null,
val series: Series? = null,
val episode: Episode? = null
) {
val id: UUID = when (type) {
BaseItemKind.MOVIE -> movie!!.id
BaseItemKind.EPISODE -> episode!!.id
BaseItemKind.SERIES -> series!!.id
else -> throw IllegalArgumentException("Invalid type: $type")
}
val title: String = when (type) {
BaseItemKind.MOVIE -> movie!!.title
BaseItemKind.EPISODE -> episode!!.title
BaseItemKind.SERIES -> series!!.name
else -> throw IllegalArgumentException("Invalid type: $type")
}
val imageUrl: String = when (type) {
BaseItemKind.MOVIE -> movie!!.heroImageUrl
BaseItemKind.EPISODE -> episode!!.heroImageUrl
BaseItemKind.SERIES -> series!!.heroImageUrl
else -> throw IllegalArgumentException("Invalid type: $type")
}
fun watched() = when (type) {
BaseItemKind.MOVIE -> movie!!.watched
BaseItemKind.EPISODE -> episode!!.watched
else -> throw IllegalArgumentException("Invalid type: $type")
}
}
data class HomeNavItem(
val id: UUID,

View File

@@ -40,6 +40,9 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil3.request.ImageRequest
import hu.bbara.purefin.common.ui.PosterCard
import hu.bbara.purefin.feature.shared.home.ContinueWatchingItem
import hu.bbara.purefin.feature.shared.home.NextUpItem
import hu.bbara.purefin.feature.shared.home.PosterItem
import hu.bbara.purefin.common.ui.components.MediaProgressBar
import hu.bbara.purefin.common.ui.components.PurefinAsyncImage
import hu.bbara.purefin.player.PlayerActivity

View File

@@ -21,11 +21,11 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import hu.bbara.purefin.app.home.ui.PosterItem
import hu.bbara.purefin.app.library.LibraryViewModel
import hu.bbara.purefin.common.ui.PosterCard
import hu.bbara.purefin.common.ui.components.PurefinIconButton
import hu.bbara.purefin.navigation.LibraryDto
import hu.bbara.purefin.core.data.navigation.LibraryDto
import hu.bbara.purefin.feature.shared.home.PosterItem
import hu.bbara.purefin.feature.shared.library.LibraryViewModel
@Composable
fun LibraryScreen(

View File

@@ -34,7 +34,7 @@ import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import hu.bbara.purefin.common.ui.components.PurefinAsyncImage
import hu.bbara.purefin.data.model.CastMember
import hu.bbara.purefin.core.model.CastMember
@Composable
fun MediaMetaChip(

View File

@@ -23,10 +23,10 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil3.request.ImageRequest
import hu.bbara.purefin.app.home.ui.PosterItem
import hu.bbara.purefin.common.ui.components.PurefinAsyncImage
import hu.bbara.purefin.common.ui.components.UnwatchedEpisodeIndicator
import hu.bbara.purefin.common.ui.components.WatchStateIndicator
import hu.bbara.purefin.feature.shared.home.PosterItem
import org.jellyfin.sdk.model.UUID
import org.jellyfin.sdk.model.api.BaseItemKind
@@ -49,11 +49,10 @@ fun PosterCard(
when (posterItem.type) {
BaseItemKind.MOVIE -> onMovieSelected(posterItem.id)
BaseItemKind.SERIES -> onSeriesSelected(posterItem.id)
BaseItemKind.EPISODE -> onEpisodeSelected(
posterItem.episode!!.seriesId,
posterItem.episode.seasonId,
posterItem.episode.id
)
BaseItemKind.EPISODE -> {
val ep = posterItem.episode!!
onEpisodeSelected(ep.seriesId, ep.seasonId, ep.id)
}
else -> {}
}
}
@@ -79,20 +78,26 @@ fun PosterCard(
contentScale = ContentScale.Crop
)
when (item.type) {
BaseItemKind.MOVIE -> WatchStateIndicator(
size = 28,
modifier = Modifier.align(Alignment.TopEnd)
.padding(8.dp),
watched = item.movie!!.watched,
started = (item.movie.progress ?: 0.0) > 0
)
BaseItemKind.EPISODE -> WatchStateIndicator(
size = 28,
modifier = Modifier.align(Alignment.TopEnd)
.padding(8.dp),
watched = item.episode!!.watched,
started = (item.episode.progress ?: 0.0) > 0
)
BaseItemKind.MOVIE -> {
val m = item.movie!!
WatchStateIndicator(
size = 28,
modifier = Modifier.align(Alignment.TopEnd)
.padding(8.dp),
watched = m.watched,
started = (m.progress ?: 0.0) > 0
)
}
BaseItemKind.EPISODE -> {
val ep = item.episode!!
WatchStateIndicator(
size = 28,
modifier = Modifier.align(Alignment.TopEnd)
.padding(8.dp),
watched = ep.watched,
started = (ep.progress ?: 0.0) > 0
)
}
BaseItemKind.SERIES -> UnwatchedEpisodeIndicator(
size = 28,
modifier = Modifier.align(Alignment.TopEnd)

View File

@@ -41,7 +41,7 @@ import hu.bbara.purefin.common.ui.PurefinComplexTextField
import hu.bbara.purefin.common.ui.PurefinPasswordField
import hu.bbara.purefin.common.ui.PurefinTextButton
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
import hu.bbara.purefin.login.viewmodel.LoginViewModel
import hu.bbara.purefin.feature.shared.login.LoginViewModel
import kotlinx.coroutines.launch
@Composable

View File

@@ -6,6 +6,7 @@ import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityRetainedComponent
import dagger.multibindings.IntoSet
import hu.bbara.purefin.core.data.navigation.Route
@Module
@InstallIn(ActivityRetainedComponent::class)

View File

@@ -6,6 +6,7 @@ import hu.bbara.purefin.app.content.movie.MovieScreen
import hu.bbara.purefin.app.content.series.SeriesScreen
import hu.bbara.purefin.app.home.HomePage
import hu.bbara.purefin.app.library.ui.LibraryScreen
import hu.bbara.purefin.core.data.navigation.Route
import hu.bbara.purefin.login.ui.LoginScreen
fun EntryProviderScope<Route>.appRouteEntryBuilder() {

View File

@@ -11,8 +11,8 @@ import androidx.core.view.WindowInsetsControllerCompat
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import dagger.hilt.android.AndroidEntryPoint
import hu.bbara.purefin.core.player.viewmodel.PlayerViewModel
import hu.bbara.purefin.player.ui.PlayerScreen
import hu.bbara.purefin.player.viewmodel.PlayerViewModel
import hu.bbara.purefin.ui.theme.AppTheme
@AndroidEntryPoint

View File

@@ -1,4 +0,0 @@
package hu.bbara.purefin.player.stream
class MediaSourceSelector {
}

View File

@@ -39,6 +39,7 @@ import androidx.media3.ui.AspectRatioFrameLayout
import androidx.media3.ui.PlayerView
import hu.bbara.purefin.common.ui.components.EmptyValueTimedVisibility
import hu.bbara.purefin.common.ui.components.ValueChangeTimedVisibility
import hu.bbara.purefin.core.player.viewmodel.PlayerViewModel
import hu.bbara.purefin.player.ui.components.PersistentOverlayContainer
import hu.bbara.purefin.player.ui.components.PlayerAdjustmentIndicator
import hu.bbara.purefin.player.ui.components.PlayerControlsOverlay
@@ -46,7 +47,6 @@ import hu.bbara.purefin.player.ui.components.PlayerGesturesLayer
import hu.bbara.purefin.player.ui.components.PlayerLoadingErrorEndCard
import hu.bbara.purefin.player.ui.components.PlayerQueuePanel
import hu.bbara.purefin.player.ui.components.rememberPersistentOverlayController
import hu.bbara.purefin.player.viewmodel.PlayerViewModel
import kotlin.math.abs
import kotlin.math.roundToInt

View File

@@ -37,8 +37,8 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import hu.bbara.purefin.common.ui.components.GhostIconButton
import hu.bbara.purefin.common.ui.components.PurefinIconButton
import hu.bbara.purefin.player.model.PlayerUiState
import hu.bbara.purefin.player.model.TrackOption
import hu.bbara.purefin.core.player.model.PlayerUiState
import hu.bbara.purefin.core.player.model.TrackOption
@Composable
fun PlayerControlsOverlay(

View File

@@ -19,7 +19,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import hu.bbara.purefin.player.model.PlayerUiState
import hu.bbara.purefin.core.player.model.PlayerUiState
@Composable
fun PlayerLoadingErrorEndCard(

View File

@@ -31,7 +31,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import hu.bbara.purefin.common.ui.components.PurefinAsyncImage
import hu.bbara.purefin.player.model.PlayerUiState
import hu.bbara.purefin.core.player.model.PlayerUiState
@Composable
fun PlayerQueuePanel(

View File

@@ -16,8 +16,8 @@ import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import hu.bbara.purefin.player.model.MarkerType
import hu.bbara.purefin.player.model.TimedMarker
import hu.bbara.purefin.core.player.model.MarkerType
import hu.bbara.purefin.core.player.model.TimedMarker
@Composable
fun PlayerSeekBar(

View File

@@ -27,7 +27,7 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import hu.bbara.purefin.common.ui.components.PurefinIconButton
import hu.bbara.purefin.player.model.TrackOption
import hu.bbara.purefin.core.player.model.TrackOption
@Composable
fun QualitySelectionButton(

View File

@@ -1,8 +1,10 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlin.compose) apply false
alias(libs.plugins.kotlin.serialization) apply false
alias(libs.plugins.ksp) apply false
alias(libs.plugins.hilt) apply false
}

View File

@@ -0,0 +1,52 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.hilt)
alias(libs.plugins.ksp)
}
android {
namespace = "hu.bbara.purefin.core.data"
compileSdk = 36
defaultConfig {
minSdk = 29
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
buildFeatures {
compose = true
}
}
kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_11)
}
}
dependencies {
implementation(project(":core:model"))
implementation(libs.jellyfin.core)
implementation(libs.kotlinx.serialization.json)
implementation(libs.hilt)
ksp(libs.hilt.compiler)
implementation(libs.datastore)
implementation(libs.okhttp)
implementation(libs.logging.interceptor)
implementation(libs.coil.compose)
implementation(libs.coil.network.okhttp)
implementation(libs.androidx.room.ktx)
ksp(libs.androidx.room.compiler)
implementation(libs.androidx.navigation3.runtime)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.ui)
}

View File

@@ -1,13 +1,14 @@
package hu.bbara.purefin.data
package hu.bbara.purefin.core.data
import hu.bbara.purefin.data.local.room.OfflineRepository
import hu.bbara.purefin.data.local.room.OnlineRepository
import hu.bbara.purefin.data.model.Episode
import hu.bbara.purefin.data.model.Library
import hu.bbara.purefin.data.model.Media
import hu.bbara.purefin.data.model.Movie
import hu.bbara.purefin.data.model.Series
import hu.bbara.purefin.session.UserSessionRepository
import hu.bbara.purefin.core.data.local.room.OfflineRepository
import hu.bbara.purefin.core.data.local.room.OnlineRepository
import hu.bbara.purefin.core.data.session.UserSessionRepository
import hu.bbara.purefin.core.model.Episode
import hu.bbara.purefin.core.model.Library
import hu.bbara.purefin.core.model.Media
import hu.bbara.purefin.core.model.MediaRepositoryState
import hu.bbara.purefin.core.model.Movie
import hu.bbara.purefin.core.model.Series
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi

View File

@@ -1,20 +1,21 @@
package hu.bbara.purefin.data
package hu.bbara.purefin.core.data
import androidx.datastore.core.DataStore
import hu.bbara.purefin.client.JellyfinApiClient
import hu.bbara.purefin.data.cache.CachedMediaItem
import hu.bbara.purefin.data.cache.HomeCache
import hu.bbara.purefin.data.local.room.OfflineDatabase
import hu.bbara.purefin.data.local.room.OfflineRoomMediaLocalDataSource
import hu.bbara.purefin.data.local.room.RoomMediaLocalDataSource
import hu.bbara.purefin.data.model.Episode
import hu.bbara.purefin.data.model.Library
import hu.bbara.purefin.data.model.Media
import hu.bbara.purefin.data.model.Movie
import hu.bbara.purefin.data.model.Season
import hu.bbara.purefin.data.model.Series
import hu.bbara.purefin.image.JellyfinImageHelper
import hu.bbara.purefin.session.UserSessionRepository
import hu.bbara.purefin.core.data.cache.CachedMediaItem
import hu.bbara.purefin.core.data.cache.HomeCache
import hu.bbara.purefin.core.data.client.JellyfinApiClient
import hu.bbara.purefin.core.data.image.JellyfinImageHelper
import hu.bbara.purefin.core.data.local.room.OfflineDatabase
import hu.bbara.purefin.core.data.local.room.OfflineRoomMediaLocalDataSource
import hu.bbara.purefin.core.data.local.room.RoomMediaLocalDataSource
import hu.bbara.purefin.core.data.session.UserSessionRepository
import hu.bbara.purefin.core.model.Episode
import hu.bbara.purefin.core.model.Library
import hu.bbara.purefin.core.model.Media
import hu.bbara.purefin.core.model.MediaRepositoryState
import hu.bbara.purefin.core.model.Movie
import hu.bbara.purefin.core.model.Season
import hu.bbara.purefin.core.model.Series
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers

View File

@@ -1,10 +1,11 @@
package hu.bbara.purefin.data
package hu.bbara.purefin.core.data
import hu.bbara.purefin.data.model.Episode
import hu.bbara.purefin.data.model.Library
import hu.bbara.purefin.data.model.Media
import hu.bbara.purefin.data.model.Movie
import hu.bbara.purefin.data.model.Series
import hu.bbara.purefin.core.model.Episode
import hu.bbara.purefin.core.model.Library
import hu.bbara.purefin.core.model.Media
import hu.bbara.purefin.core.model.MediaRepositoryState
import hu.bbara.purefin.core.model.Movie
import hu.bbara.purefin.core.model.Series
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import java.util.UUID

View File

@@ -1,11 +1,11 @@
package hu.bbara.purefin.data
package hu.bbara.purefin.core.data
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import hu.bbara.purefin.data.local.room.OnlineRepository
import hu.bbara.purefin.data.local.room.OfflineRepository
import hu.bbara.purefin.core.data.local.room.OfflineRepository
import hu.bbara.purefin.core.data.local.room.OnlineRepository
@Module
@InstallIn(SingletonComponent::class)

View File

@@ -1,12 +1,13 @@
package hu.bbara.purefin.data
package hu.bbara.purefin.core.data
import hu.bbara.purefin.data.local.room.OfflineDatabase
import hu.bbara.purefin.data.local.room.OfflineRoomMediaLocalDataSource
import hu.bbara.purefin.data.model.Episode
import hu.bbara.purefin.data.model.Library
import hu.bbara.purefin.data.model.Media
import hu.bbara.purefin.data.model.Movie
import hu.bbara.purefin.data.model.Series
import hu.bbara.purefin.core.data.local.room.OfflineDatabase
import hu.bbara.purefin.core.data.local.room.OfflineRoomMediaLocalDataSource
import hu.bbara.purefin.core.model.Episode
import hu.bbara.purefin.core.model.Library
import hu.bbara.purefin.core.model.Media
import hu.bbara.purefin.core.model.MediaRepositoryState
import hu.bbara.purefin.core.model.Movie
import hu.bbara.purefin.core.model.Series
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.cache
package hu.bbara.purefin.core.data.cache
import kotlinx.serialization.Serializable

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.cache
package hu.bbara.purefin.core.data.cache
import android.content.Context
import androidx.datastore.core.DataStore

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.cache
package hu.bbara.purefin.core.data.cache
import androidx.datastore.core.CorruptionException
import androidx.datastore.core.Serializer

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.client
package hu.bbara.purefin.core.data.client
import android.media.MediaCodecList
import android.util.Log

View File

@@ -1,6 +1,5 @@
package hu.bbara.purefin.client
package hu.bbara.purefin.core.data.client
import android.media.MediaCodecInfo
import android.media.MediaCodecList
import android.util.Log

View File

@@ -1,9 +1,9 @@
package hu.bbara.purefin.client
package hu.bbara.purefin.core.data.client
import android.content.Context
import android.util.Log
import dagger.hilt.android.qualifiers.ApplicationContext
import hu.bbara.purefin.session.UserSessionRepository
import hu.bbara.purefin.core.data.session.UserSessionRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withContext

View File

@@ -1,6 +1,6 @@
package hu.bbara.purefin.client
package hu.bbara.purefin.core.data.client
import hu.bbara.purefin.session.UserSessionRepository
import hu.bbara.purefin.core.data.session.UserSessionRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob

View File

@@ -1,6 +1,6 @@
package hu.bbara.purefin.domain.usecase
package hu.bbara.purefin.core.data.domain.usecase
import hu.bbara.purefin.data.MediaRepository
import hu.bbara.purefin.core.data.MediaRepository
import javax.inject.Inject
class RefreshHomeDataUseCase @Inject constructor(

View File

@@ -1,6 +1,6 @@
package hu.bbara.purefin.domain.usecase
package hu.bbara.purefin.core.data.domain.usecase
import hu.bbara.purefin.data.MediaRepository
import hu.bbara.purefin.core.data.MediaRepository
import java.util.UUID
import javax.inject.Inject

View File

@@ -1,10 +1,10 @@
package hu.bbara.purefin.image
package hu.bbara.purefin.core.data.image
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import hu.bbara.purefin.client.JellyfinAuthInterceptor
import hu.bbara.purefin.core.data.client.JellyfinAuthInterceptor
import okhttp3.OkHttpClient
import javax.inject.Singleton

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.image
package hu.bbara.purefin.core.data.image
import org.jellyfin.sdk.model.UUID
import org.jellyfin.sdk.model.api.ImageType

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.local.room
package hu.bbara.purefin.core.data.local.room
import androidx.room.Entity
import androidx.room.Index

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.local.room
package hu.bbara.purefin.core.data.local.room
import javax.inject.Qualifier

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.local.room
package hu.bbara.purefin.core.data.local.room
import androidx.room.Entity
import androidx.room.ForeignKey

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.local.room
package hu.bbara.purefin.core.data.local.room
import androidx.room.Entity
import androidx.room.PrimaryKey

View File

@@ -1,14 +1,15 @@
package hu.bbara.purefin.data.local.room
package hu.bbara.purefin.core.data.local.room
import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import hu.bbara.purefin.data.local.room.dao.CastMemberDao
import hu.bbara.purefin.data.local.room.dao.EpisodeDao
import hu.bbara.purefin.data.local.room.dao.MovieDao
import hu.bbara.purefin.data.local.room.dao.SeasonDao
import hu.bbara.purefin.data.local.room.dao.SeriesDao
import hu.bbara.purefin.data.local.room.dao.LibraryDao
import hu.bbara.purefin.core.data.local.room.dao.CastMemberDao
import hu.bbara.purefin.core.data.local.room.dao.EpisodeDao
import hu.bbara.purefin.core.data.local.room.dao.LibraryDao
import hu.bbara.purefin.core.data.local.room.dao.MovieDao
import hu.bbara.purefin.core.data.local.room.dao.SeasonDao
import hu.bbara.purefin.core.data.local.room.dao.SeriesDao
@Database(
entities = [
MovieEntity::class,

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.local.room
package hu.bbara.purefin.core.data.local.room
import android.content.Context
import androidx.room.Room
@@ -7,12 +7,12 @@ import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import hu.bbara.purefin.data.local.room.dao.CastMemberDao
import hu.bbara.purefin.data.local.room.dao.EpisodeDao
import hu.bbara.purefin.data.local.room.dao.LibraryDao
import hu.bbara.purefin.data.local.room.dao.MovieDao
import hu.bbara.purefin.data.local.room.dao.SeasonDao
import hu.bbara.purefin.data.local.room.dao.SeriesDao
import hu.bbara.purefin.core.data.local.room.dao.CastMemberDao
import hu.bbara.purefin.core.data.local.room.dao.EpisodeDao
import hu.bbara.purefin.core.data.local.room.dao.LibraryDao
import hu.bbara.purefin.core.data.local.room.dao.MovieDao
import hu.bbara.purefin.core.data.local.room.dao.SeasonDao
import hu.bbara.purefin.core.data.local.room.dao.SeriesDao
import javax.inject.Singleton
@Module

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.local.room
package hu.bbara.purefin.core.data.local.room
import androidx.room.Entity
import androidx.room.ForeignKey

View File

@@ -1,14 +1,14 @@
package hu.bbara.purefin.data.local.room
package hu.bbara.purefin.core.data.local.room
import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import hu.bbara.purefin.data.local.room.dao.CastMemberDao
import hu.bbara.purefin.data.local.room.dao.EpisodeDao
import hu.bbara.purefin.data.local.room.dao.MovieDao
import hu.bbara.purefin.data.local.room.dao.SeasonDao
import hu.bbara.purefin.data.local.room.dao.SeriesDao
import hu.bbara.purefin.data.local.room.dao.LibraryDao
import hu.bbara.purefin.core.data.local.room.dao.CastMemberDao
import hu.bbara.purefin.core.data.local.room.dao.EpisodeDao
import hu.bbara.purefin.core.data.local.room.dao.LibraryDao
import hu.bbara.purefin.core.data.local.room.dao.MovieDao
import hu.bbara.purefin.core.data.local.room.dao.SeasonDao
import hu.bbara.purefin.core.data.local.room.dao.SeriesDao
@Database(
entities = [

View File

@@ -1,23 +1,22 @@
package hu.bbara.purefin.data.local.room
package hu.bbara.purefin.core.data.local.room
import androidx.room.withTransaction
import hu.bbara.purefin.data.local.room.dao.CastMemberDao
import hu.bbara.purefin.data.local.room.dao.EpisodeDao
import hu.bbara.purefin.data.local.room.dao.LibraryDao
import hu.bbara.purefin.data.local.room.dao.MovieDao
import hu.bbara.purefin.data.local.room.dao.SeasonDao
import hu.bbara.purefin.data.local.room.dao.SeriesDao
import hu.bbara.purefin.data.model.CastMember
import hu.bbara.purefin.data.model.Episode
import hu.bbara.purefin.data.model.Library
import hu.bbara.purefin.data.model.Movie
import hu.bbara.purefin.data.model.Season
import hu.bbara.purefin.data.model.Series
import hu.bbara.purefin.core.data.local.room.dao.CastMemberDao
import hu.bbara.purefin.core.data.local.room.dao.EpisodeDao
import hu.bbara.purefin.core.data.local.room.dao.LibraryDao
import hu.bbara.purefin.core.data.local.room.dao.MovieDao
import hu.bbara.purefin.core.data.local.room.dao.SeasonDao
import hu.bbara.purefin.core.data.local.room.dao.SeriesDao
import hu.bbara.purefin.core.model.CastMember
import hu.bbara.purefin.core.model.Episode
import hu.bbara.purefin.core.model.Library
import hu.bbara.purefin.core.model.Movie
import hu.bbara.purefin.core.model.Season
import hu.bbara.purefin.core.model.Series
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import org.jellyfin.sdk.model.api.CollectionType
import java.util.UUID
import javax.inject.Inject
import javax.inject.Singleton
@Singleton

View File

@@ -1,24 +1,23 @@
package hu.bbara.purefin.data.local.room
package hu.bbara.purefin.core.data.local.room
import androidx.room.withTransaction
import hu.bbara.purefin.data.local.room.dao.CastMemberDao
import hu.bbara.purefin.data.local.room.dao.EpisodeDao
import hu.bbara.purefin.data.local.room.dao.LibraryDao
import hu.bbara.purefin.data.local.room.dao.MovieDao
import hu.bbara.purefin.data.local.room.dao.SeasonDao
import hu.bbara.purefin.data.local.room.dao.SeriesDao
import hu.bbara.purefin.data.model.CastMember
import hu.bbara.purefin.data.model.Episode
import hu.bbara.purefin.data.model.Library
import hu.bbara.purefin.data.model.Movie
import hu.bbara.purefin.data.model.Season
import hu.bbara.purefin.data.model.Series
import hu.bbara.purefin.core.data.local.room.dao.CastMemberDao
import hu.bbara.purefin.core.data.local.room.dao.EpisodeDao
import hu.bbara.purefin.core.data.local.room.dao.LibraryDao
import hu.bbara.purefin.core.data.local.room.dao.MovieDao
import hu.bbara.purefin.core.data.local.room.dao.SeasonDao
import hu.bbara.purefin.core.data.local.room.dao.SeriesDao
import hu.bbara.purefin.core.model.CastMember
import hu.bbara.purefin.core.model.Episode
import hu.bbara.purefin.core.model.Library
import hu.bbara.purefin.core.model.Movie
import hu.bbara.purefin.core.model.Season
import hu.bbara.purefin.core.model.Series
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import org.jellyfin.sdk.model.api.CollectionType
import java.util.UUID
import javax.inject.Singleton
import kotlin.collections.map
@Singleton
class RoomMediaLocalDataSource(

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.local.room
package hu.bbara.purefin.core.data.local.room
import androidx.room.Embedded
import androidx.room.Relation

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.local.room
package hu.bbara.purefin.core.data.local.room
import androidx.room.Entity
import androidx.room.ForeignKey

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.local.room
package hu.bbara.purefin.core.data.local.room
import androidx.room.Entity
import androidx.room.ForeignKey

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.local.room
package hu.bbara.purefin.core.data.local.room
import androidx.room.TypeConverter
import java.util.UUID

View File

@@ -1,9 +1,9 @@
package hu.bbara.purefin.data.local.room.dao
package hu.bbara.purefin.core.data.local.room.dao
import androidx.room.Dao
import androidx.room.Query
import androidx.room.Upsert
import hu.bbara.purefin.data.local.room.CastMemberEntity
import hu.bbara.purefin.core.data.local.room.CastMemberEntity
import java.util.UUID
@Dao

View File

@@ -1,9 +1,9 @@
package hu.bbara.purefin.data.local.room.dao
package hu.bbara.purefin.core.data.local.room.dao
import androidx.room.Dao
import androidx.room.Query
import androidx.room.Upsert
import hu.bbara.purefin.data.local.room.EpisodeEntity
import hu.bbara.purefin.core.data.local.room.EpisodeEntity
import kotlinx.coroutines.flow.Flow
import java.util.UUID

View File

@@ -1,10 +1,10 @@
package hu.bbara.purefin.data.local.room.dao
package hu.bbara.purefin.core.data.local.room.dao
import androidx.room.Dao
import androidx.room.Query
import androidx.room.Upsert
import hu.bbara.purefin.data.local.room.LibraryEntity
import hu.bbara.purefin.data.local.room.LibraryWithContent
import hu.bbara.purefin.core.data.local.room.LibraryEntity
import hu.bbara.purefin.core.data.local.room.LibraryWithContent
import kotlinx.coroutines.flow.Flow
@Dao

View File

@@ -1,9 +1,9 @@
package hu.bbara.purefin.data.local.room.dao
package hu.bbara.purefin.core.data.local.room.dao
import androidx.room.Dao
import androidx.room.Query
import androidx.room.Upsert
import hu.bbara.purefin.data.local.room.MovieEntity
import hu.bbara.purefin.core.data.local.room.MovieEntity
import kotlinx.coroutines.flow.Flow
import java.util.UUID

View File

@@ -1,9 +1,9 @@
package hu.bbara.purefin.data.local.room.dao
package hu.bbara.purefin.core.data.local.room.dao
import androidx.room.Dao
import androidx.room.Query
import androidx.room.Upsert
import hu.bbara.purefin.data.local.room.SeasonEntity
import hu.bbara.purefin.core.data.local.room.SeasonEntity
import java.util.UUID
@Dao

View File

@@ -1,11 +1,11 @@
package hu.bbara.purefin.data.local.room.dao
package hu.bbara.purefin.core.data.local.room.dao
import androidx.room.Dao
import androidx.room.Query
import androidx.room.Transaction
import androidx.room.Upsert
import hu.bbara.purefin.data.local.room.SeriesEntity
import hu.bbara.purefin.data.local.room.SeriesWithSeasonsAndEpisodes
import hu.bbara.purefin.core.data.local.room.SeriesEntity
import hu.bbara.purefin.core.data.local.room.SeriesWithSeasonsAndEpisodes
import kotlinx.coroutines.flow.Flow
import java.util.UUID

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.navigation
package hu.bbara.purefin.core.data.navigation
import kotlinx.serialization.Serializable
import org.jellyfin.sdk.model.serializer.UUIDSerializer

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.navigation
package hu.bbara.purefin.core.data.navigation
import kotlinx.serialization.Serializable
import org.jellyfin.sdk.model.UUID

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.navigation
package hu.bbara.purefin.core.data.navigation
import kotlinx.serialization.Serializable
import org.jellyfin.sdk.model.serializer.UUIDSerializer

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.navigation
package hu.bbara.purefin.core.data.navigation
import androidx.compose.runtime.ProvidableCompositionLocal
import androidx.compose.runtime.staticCompositionLocalOf

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.navigation
package hu.bbara.purefin.core.data.navigation
import dagger.Module
import dagger.Provides

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.navigation
package hu.bbara.purefin.core.data.navigation
import androidx.navigation3.runtime.NavKey
import kotlinx.serialization.Serializable

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.navigation
package hu.bbara.purefin.core.data.navigation
import kotlinx.serialization.Serializable
import org.jellyfin.sdk.model.serializer.UUIDSerializer

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.session
package hu.bbara.purefin.core.data.session
import kotlinx.serialization.Serializable
import org.jellyfin.sdk.model.serializer.UUIDSerializer

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.session
package hu.bbara.purefin.core.data.session
import android.content.Context
import androidx.datastore.core.DataStore

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.session
package hu.bbara.purefin.core.data.session
import androidx.datastore.core.DataStore
import kotlinx.coroutines.flow.Flow

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.session
package hu.bbara.purefin.core.data.session
import androidx.datastore.core.CorruptionException
import androidx.datastore.core.Serializer

View File

@@ -0,0 +1,30 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android)
}
android {
namespace = "hu.bbara.purefin.core.model"
compileSdk = 36
defaultConfig {
minSdk = 29
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}
kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_11)
}
}
dependencies {
implementation(libs.jellyfin.core)
}

View File

@@ -1,7 +1,7 @@
package hu.bbara.purefin.data.model
package hu.bbara.purefin.core.model
data class CastMember(
val name: String,
val role: String,
val imageUrl: String?
)
)

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.model
package hu.bbara.purefin.core.model
import java.util.UUID

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.model
package hu.bbara.purefin.core.model
import org.jellyfin.sdk.model.api.CollectionType
import java.util.UUID

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.model
package hu.bbara.purefin.core.model
import org.jellyfin.sdk.model.api.BaseItemKind
import java.util.UUID

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data
package hu.bbara.purefin.core.model
sealed interface MediaRepositoryState {
data object Loading : MediaRepositoryState

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.model
package hu.bbara.purefin.core.model
import java.util.UUID

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.model
package hu.bbara.purefin.core.model
import java.util.UUID
@@ -10,5 +10,4 @@ data class Season(
val unwatchedEpisodeCount: Int,
val episodeCount: Int,
val episodes: List<Episode>
) {
}
)

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.data.model
package hu.bbara.purefin.core.model
import java.util.UUID
@@ -13,5 +13,4 @@ data class Series(
val seasonCount: Int,
val seasons: List<Season>,
val cast: List<CastMember>
) {
}
)

View File

@@ -0,0 +1,42 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.hilt)
alias(libs.plugins.ksp)
}
android {
namespace = "hu.bbara.purefin.core.player"
compileSdk = 36
defaultConfig {
minSdk = 29
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}
kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_11)
}
}
dependencies {
implementation(project(":core:model"))
implementation(project(":core:data"))
implementation(libs.hilt)
ksp(libs.hilt.compiler)
implementation(libs.medi3.exoplayer)
implementation(libs.media3.datasource.okhttp)
implementation(libs.datastore)
implementation(libs.kotlinx.serialization.json)
implementation(libs.jellyfin.core)
implementation(libs.okhttp)
}

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.player.data
package hu.bbara.purefin.core.player.data
import android.util.Log
import androidx.annotation.OptIn
@@ -9,9 +9,9 @@ import androidx.media3.common.MediaMetadata
import androidx.media3.common.MimeTypes
import androidx.media3.common.util.UnstableApi
import dagger.hilt.android.scopes.ViewModelScoped
import hu.bbara.purefin.client.JellyfinApiClient
import hu.bbara.purefin.image.JellyfinImageHelper
import hu.bbara.purefin.session.UserSessionRepository
import hu.bbara.purefin.core.data.client.JellyfinApiClient
import hu.bbara.purefin.core.data.image.JellyfinImageHelper
import hu.bbara.purefin.core.data.session.UserSessionRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withContext

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.player.manager
package hu.bbara.purefin.core.player.manager
import androidx.annotation.OptIn
import androidx.media3.common.C
@@ -9,14 +9,13 @@ import androidx.media3.common.TrackSelectionOverride
import androidx.media3.common.Tracks
import androidx.media3.common.util.UnstableApi
import dagger.hilt.android.scopes.ViewModelScoped
import hu.bbara.purefin.player.model.QueueItemUi
import hu.bbara.purefin.player.model.TrackOption
import hu.bbara.purefin.player.model.TrackType
import hu.bbara.purefin.player.preference.AudioTrackProperties
import hu.bbara.purefin.player.preference.SubtitleTrackProperties
import hu.bbara.purefin.player.preference.TrackMatcher
import hu.bbara.purefin.player.preference.TrackPreferencesRepository
import javax.inject.Inject
import hu.bbara.purefin.core.player.model.QueueItemUi
import hu.bbara.purefin.core.player.model.TrackOption
import hu.bbara.purefin.core.player.model.TrackType
import hu.bbara.purefin.core.player.preference.AudioTrackProperties
import hu.bbara.purefin.core.player.preference.SubtitleTrackProperties
import hu.bbara.purefin.core.player.preference.TrackMatcher
import hu.bbara.purefin.core.player.preference.TrackPreferencesRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
@@ -29,6 +28,7 @@ import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import javax.inject.Inject
/**
* Encapsulates the Media3 [Player] wiring and exposes reactive updates for the UI layer.

View File

@@ -1,9 +1,9 @@
package hu.bbara.purefin.player.manager
package hu.bbara.purefin.core.player.manager
import android.util.Log
import dagger.hilt.android.scopes.ViewModelScoped
import hu.bbara.purefin.client.JellyfinApiClient
import hu.bbara.purefin.domain.usecase.UpdateWatchProgressUseCase
import hu.bbara.purefin.core.data.client.JellyfinApiClient
import hu.bbara.purefin.core.data.domain.usecase.UpdateWatchProgressUseCase
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job

View File

@@ -1,12 +1,12 @@
package hu.bbara.purefin.player.manager
package hu.bbara.purefin.core.player.manager
import androidx.annotation.OptIn
import androidx.media3.common.C
import androidx.media3.common.Format
import androidx.media3.common.Tracks
import androidx.media3.common.util.UnstableApi
import hu.bbara.purefin.player.model.TrackOption
import hu.bbara.purefin.player.model.TrackType
import hu.bbara.purefin.core.player.model.TrackOption
import hu.bbara.purefin.core.player.model.TrackType
import javax.inject.Inject
data class TrackSelectionState(

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.player.model
package hu.bbara.purefin.core.player.model
data class PlayerUiState(
val isPlaying: Boolean = false,

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.player.model
package hu.bbara.purefin.core.player.model
import android.net.Uri
import androidx.media3.common.MediaItem

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.player.module
package hu.bbara.purefin.core.player.module
import android.app.Application
import androidx.annotation.OptIn

View File

@@ -1,7 +1,7 @@
package hu.bbara.purefin.player.preference
package hu.bbara.purefin.core.player.preference
import hu.bbara.purefin.player.model.TrackOption
import hu.bbara.purefin.player.model.TrackType
import hu.bbara.purefin.core.player.model.TrackOption
import hu.bbara.purefin.core.player.model.TrackType
import javax.inject.Inject
class TrackMatcher @Inject constructor() {

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.player.preference
package hu.bbara.purefin.core.player.preference
import kotlinx.serialization.Serializable

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.player.preference
package hu.bbara.purefin.core.player.preference
import android.content.Context
import androidx.datastore.core.DataStore

View File

@@ -1,4 +1,4 @@
package hu.bbara.purefin.player.preference
package hu.bbara.purefin.core.player.preference
import androidx.datastore.core.DataStore
import kotlinx.coroutines.flow.Flow

Some files were not shown because too many files have changed in this diff Show More