refactor: change dependency structure. core should not depend on data. Move repository interfaces to core. Move hilt bindings in the data model.

This commit is contained in:
2026-04-24 19:02:26 +02:00
parent 354314710b
commit 2433ececac
44 changed files with 73 additions and 53 deletions

View File

@@ -37,7 +37,7 @@ import coil3.request.crossfade
import coil3.util.DebugLogger
import dagger.hilt.android.AndroidEntryPoint
import hu.bbara.purefin.data.SessionBootstrapper
import hu.bbara.purefin.data.session.UserSessionRepository
import hu.bbara.purefin.data.UserSessionRepository
import hu.bbara.purefin.navigation.NavigationCommand
import hu.bbara.purefin.navigation.NavigationManager
import hu.bbara.purefin.navigation.Route

View File

@@ -38,7 +38,7 @@ import coil3.util.DebugLogger
import dagger.hilt.android.AndroidEntryPoint
import hu.bbara.purefin.data.SessionBootstrapper
import hu.bbara.purefin.jellyfin.JellyfinAuthInterceptor
import hu.bbara.purefin.data.session.UserSessionRepository
import hu.bbara.purefin.data.UserSessionRepository
import hu.bbara.purefin.navigation.LocalNavigationBackStack
import hu.bbara.purefin.navigation.LocalNavigationManager
import hu.bbara.purefin.navigation.NavigationCommand

View File

@@ -29,7 +29,6 @@ kotlin {
}
dependencies {
implementation(project(":data"))
implementation(project(":core-model"))
implementation(libs.hilt)
ksp(libs.hilt.compiler)

View File

@@ -0,0 +1,11 @@
package hu.bbara.purefin
import javax.inject.Qualifier
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class Online
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class Offline

View File

@@ -1,7 +1,7 @@
package hu.bbara.purefin.data
import hu.bbara.purefin.data.catalog.InMemoryMediaRepository
import hu.bbara.purefin.data.catalog.OfflineMediaRepository
import hu.bbara.purefin.Offline
import hu.bbara.purefin.Online
import hu.bbara.purefin.model.Episode
import hu.bbara.purefin.model.Movie
import hu.bbara.purefin.model.Series
@@ -22,8 +22,8 @@ import javax.inject.Singleton
@OptIn(ExperimentalCoroutinesApi::class)
@Singleton
class CompositeMediaRepository @Inject constructor(
private val offlineRepository: OfflineMediaRepository,
private val onlineRepository: InMemoryMediaRepository,
@Offline private val offlineRepository: MediaRepository,
@Online private val onlineRepository: MediaRepository,
) : MediaCatalogReader, MediaProgressWriter {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)

View File

@@ -0,0 +1,4 @@
package hu.bbara.purefin.data
interface MediaRepository : MediaCatalogReader, MediaProgressWriter {
}

View File

@@ -3,8 +3,8 @@ package hu.bbara.purefin.data
import hu.bbara.purefin.model.Episode
import hu.bbara.purefin.model.Movie
import hu.bbara.purefin.model.Series
import java.util.UUID
import kotlinx.coroutines.flow.StateFlow
import java.util.UUID
interface OfflineCatalogReader {
val movies: StateFlow<Map<UUID, Movie>>

View File

@@ -1,7 +1,7 @@
package hu.bbara.purefin.data
import java.util.UUID
import kotlinx.coroutines.flow.Flow
import java.util.UUID
interface SmartDownloadStore {
suspend fun enable(seriesId: UUID)

View File

@@ -1,7 +1,7 @@
package hu.bbara.purefin.data.session
package hu.bbara.purefin.data
import java.util.UUID
import kotlinx.coroutines.flow.Flow
import java.util.UUID
interface UserSessionRepository {
val serverUrl: Flow<String>

View File

@@ -5,7 +5,7 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import hu.bbara.purefin.data.HomeRepository
import hu.bbara.purefin.data.MediaCatalogReader
import hu.bbara.purefin.data.session.UserSessionRepository
import hu.bbara.purefin.data.UserSessionRepository
import hu.bbara.purefin.download.MediaDownloadController
import hu.bbara.purefin.model.LibraryKind
import hu.bbara.purefin.model.Media

View File

@@ -3,7 +3,8 @@ package hu.bbara.purefin.feature.downloads
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import hu.bbara.purefin.data.OfflineCatalogReader
import hu.bbara.purefin.Offline
import hu.bbara.purefin.data.MediaRepository
import hu.bbara.purefin.download.MediaDownloadController
import hu.bbara.purefin.image.ArtworkKind
import hu.bbara.purefin.image.ImageUrlBuilder
@@ -22,7 +23,7 @@ import javax.inject.Inject
@HiltViewModel
class DownloadsViewModel @Inject constructor(
private val offlineCatalogReader: OfflineCatalogReader,
@Offline private val offlineCatalogReader: MediaRepository,
private val navigationManager: NavigationManager,
private val downloadManager: MediaDownloadController,
) : ViewModel() {

View File

@@ -4,7 +4,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import hu.bbara.purefin.data.AuthenticationRepository
import hu.bbara.purefin.data.session.UserSessionRepository
import hu.bbara.purefin.data.UserSessionRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow

View File

@@ -4,8 +4,8 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import hu.bbara.purefin.data.MediaCatalogReader
import hu.bbara.purefin.data.UserSessionRepository
import hu.bbara.purefin.image.ImageUrlBuilder
import hu.bbara.purefin.data.session.UserSessionRepository
import java.util.UUID
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.MutableStateFlow

View File

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

View File

@@ -5,19 +5,14 @@ import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import hu.bbara.purefin.data.CompositeMediaRepository
import hu.bbara.purefin.data.HomeRepository
import hu.bbara.purefin.data.MediaCatalogReader
import hu.bbara.purefin.data.MediaProgressWriter
import hu.bbara.purefin.data.catalog.InMemoryAppContentRepository
@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {
@Binds
abstract fun bindHomeRepository(impl: InMemoryAppContentRepository): HomeRepository
@Binds
abstract fun bindMediaCatalogReader(impl: CompositeMediaRepository): MediaCatalogReader

View File

@@ -1,8 +1,7 @@
package hu.bbara.purefin.navigation
import java.util.UUID
import kotlinx.serialization.Serializable
import hu.bbara.purefin.navigation.UuidSerializer
import java.util.UUID
@Serializable
data class EpisodeDto(

View File

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

View File

@@ -4,7 +4,7 @@ import android.util.Log
import androidx.datastore.core.DataStore
import hu.bbara.purefin.data.HomeRepository
import hu.bbara.purefin.data.NetworkMonitor
import hu.bbara.purefin.data.session.UserSessionRepository
import hu.bbara.purefin.data.UserSessionRepository
import hu.bbara.purefin.image.ArtworkKind
import hu.bbara.purefin.image.ImageUrlBuilder
import hu.bbara.purefin.model.Episode

View File

@@ -1,21 +1,13 @@
package hu.bbara.purefin.data.catalog
import hu.bbara.purefin.data.MediaCatalogReader
import hu.bbara.purefin.data.MediaProgressWriter
import hu.bbara.purefin.data.MediaRepository
import hu.bbara.purefin.data.UserSessionRepository
import hu.bbara.purefin.data.jellyfin.client.JellyfinApiClient
import hu.bbara.purefin.image.ImageUrlBuilder
import hu.bbara.purefin.data.session.UserSessionRepository
import hu.bbara.purefin.model.Episode
import hu.bbara.purefin.model.Movie
import hu.bbara.purefin.model.Season
import hu.bbara.purefin.model.Series
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.Locale
import java.util.UUID
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
@@ -28,12 +20,19 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import org.jellyfin.sdk.model.api.BaseItemDto
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.Locale
import java.util.UUID
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class InMemoryMediaRepository @Inject constructor(
private val userSessionRepository: UserSessionRepository,
private val jellyfinApiClient: JellyfinApiClient,
) : MediaCatalogReader, MediaProgressWriter {
) : MediaRepository {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)

View File

@@ -1,15 +1,10 @@
package hu.bbara.purefin.data.catalog
import hu.bbara.purefin.data.MediaCatalogReader
import hu.bbara.purefin.data.MediaProgressWriter
import hu.bbara.purefin.data.OfflineCatalogReader
import hu.bbara.purefin.data.MediaRepository
import hu.bbara.purefin.data.offline.room.offline.OfflineRoomMediaLocalDataSource
import hu.bbara.purefin.model.Episode
import hu.bbara.purefin.model.Movie
import hu.bbara.purefin.model.Series
import java.util.UUID
import javax.inject.Inject
import javax.inject.Singleton
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
@@ -17,11 +12,14 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.stateIn
import java.util.UUID
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class OfflineMediaRepository @Inject constructor(
private val localDataSource: OfflineRoomMediaLocalDataSource,
) : OfflineCatalogReader, MediaCatalogReader, MediaProgressWriter {
) : MediaRepository {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
override val movies: StateFlow<Map<UUID, Movie>> = localDataSource.moviesFlow

View File

@@ -8,7 +8,7 @@ import androidx.media3.common.MediaMetadata
import androidx.media3.common.util.UnstableApi
import hu.bbara.purefin.data.PlayableMediaRepository
import hu.bbara.purefin.data.PlaybackReportContext
import hu.bbara.purefin.data.session.UserSessionRepository
import hu.bbara.purefin.data.UserSessionRepository
import hu.bbara.purefin.image.ArtworkKind
import hu.bbara.purefin.image.ImageUrlBuilder
import hu.bbara.purefin.model.MediaSegment

View File

@@ -5,7 +5,7 @@ import android.util.Log
import dagger.hilt.android.qualifiers.ApplicationContext
import hu.bbara.purefin.data.PlaybackMethod
import hu.bbara.purefin.data.PlaybackReportContext
import hu.bbara.purefin.data.session.UserSessionRepository
import hu.bbara.purefin.data.UserSessionRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withContext

View File

@@ -4,7 +4,7 @@ import hu.bbara.purefin.data.DownloadMediaSourceResolver
import hu.bbara.purefin.data.EpisodeDownloadSource
import hu.bbara.purefin.data.MovieDownloadSource
import hu.bbara.purefin.data.PlaybackMethod
import hu.bbara.purefin.data.session.UserSessionRepository
import hu.bbara.purefin.data.UserSessionRepository
import hu.bbara.purefin.data.jellyfin.client.JellyfinApiClient
import hu.bbara.purefin.data.jellyfin.playback.PlaybackDecisionResolver
import hu.bbara.purefin.data.jellyfin.playback.playbackCustomCacheKey

View File

@@ -1,7 +1,7 @@
package hu.bbara.purefin.data.jellyfin.playback
import android.util.Log
import hu.bbara.purefin.data.session.UserSessionRepository
import hu.bbara.purefin.data.UserSessionRepository
import hu.bbara.purefin.data.jellyfin.client.JellyfinApiClient
import java.util.UUID
import java.util.concurrent.ConcurrentHashMap

View File

@@ -2,7 +2,7 @@ package hu.bbara.purefin.data.jellyfin.session
import android.util.Log
import hu.bbara.purefin.data.AuthenticationRepository
import hu.bbara.purefin.data.session.UserSessionRepository
import hu.bbara.purefin.data.UserSessionRepository
import hu.bbara.purefin.data.jellyfin.client.JellyfinApiClient
import javax.inject.Inject
import javax.inject.Singleton

View File

@@ -10,7 +10,7 @@ import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import hu.bbara.purefin.data.session.UserSessionRepository
import hu.bbara.purefin.data.UserSessionRepository
import javax.inject.Singleton
@Module

View File

@@ -1,7 +1,7 @@
package hu.bbara.purefin.data.jellyfin.session
import androidx.datastore.core.DataStore
import hu.bbara.purefin.data.session.UserSessionRepository
import hu.bbara.purefin.data.UserSessionRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.first

View File

@@ -4,7 +4,12 @@ import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import hu.bbara.purefin.data.OfflineCatalogReader
import hu.bbara.purefin.Offline
import hu.bbara.purefin.Online
import hu.bbara.purefin.data.HomeRepository
import hu.bbara.purefin.data.MediaRepository
import hu.bbara.purefin.data.catalog.InMemoryAppContentRepository
import hu.bbara.purefin.data.catalog.InMemoryMediaRepository
import hu.bbara.purefin.data.catalog.OfflineMediaRepository
@Module
@@ -12,5 +17,13 @@ import hu.bbara.purefin.data.catalog.OfflineMediaRepository
abstract class MediaRepositoryModule {
@Binds
abstract fun bindOfflineCatalogReader(impl: OfflineMediaRepository): OfflineCatalogReader
@Online
abstract fun bindOnlineRepository(impl: InMemoryMediaRepository): MediaRepository
@Binds
@Offline
abstract fun bindOfflineRepository(impl: OfflineMediaRepository): MediaRepository
@Binds
abstract fun bindHomeRepository(impl: InMemoryAppContentRepository): HomeRepository
}