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 coil3.util.DebugLogger
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import hu.bbara.purefin.data.SessionBootstrapper 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.NavigationCommand
import hu.bbara.purefin.navigation.NavigationManager import hu.bbara.purefin.navigation.NavigationManager
import hu.bbara.purefin.navigation.Route import hu.bbara.purefin.navigation.Route

View File

@@ -38,7 +38,7 @@ import coil3.util.DebugLogger
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import hu.bbara.purefin.data.SessionBootstrapper import hu.bbara.purefin.data.SessionBootstrapper
import hu.bbara.purefin.jellyfin.JellyfinAuthInterceptor 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.LocalNavigationBackStack
import hu.bbara.purefin.navigation.LocalNavigationManager import hu.bbara.purefin.navigation.LocalNavigationManager
import hu.bbara.purefin.navigation.NavigationCommand import hu.bbara.purefin.navigation.NavigationCommand

View File

@@ -29,7 +29,6 @@ kotlin {
} }
dependencies { dependencies {
implementation(project(":data"))
implementation(project(":core-model")) implementation(project(":core-model"))
implementation(libs.hilt) implementation(libs.hilt)
ksp(libs.hilt.compiler) 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 package hu.bbara.purefin.data
import hu.bbara.purefin.data.catalog.InMemoryMediaRepository import hu.bbara.purefin.Offline
import hu.bbara.purefin.data.catalog.OfflineMediaRepository import hu.bbara.purefin.Online
import hu.bbara.purefin.model.Episode import hu.bbara.purefin.model.Episode
import hu.bbara.purefin.model.Movie import hu.bbara.purefin.model.Movie
import hu.bbara.purefin.model.Series import hu.bbara.purefin.model.Series
@@ -22,8 +22,8 @@ import javax.inject.Singleton
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
@Singleton @Singleton
class CompositeMediaRepository @Inject constructor( class CompositeMediaRepository @Inject constructor(
private val offlineRepository: OfflineMediaRepository, @Offline private val offlineRepository: MediaRepository,
private val onlineRepository: InMemoryMediaRepository, @Online private val onlineRepository: MediaRepository,
) : MediaCatalogReader, MediaProgressWriter { ) : MediaCatalogReader, MediaProgressWriter {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO) 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.Episode
import hu.bbara.purefin.model.Movie import hu.bbara.purefin.model.Movie
import hu.bbara.purefin.model.Series import hu.bbara.purefin.model.Series
import java.util.UUID
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import java.util.UUID
interface OfflineCatalogReader { interface OfflineCatalogReader {
val movies: StateFlow<Map<UUID, Movie>> val movies: StateFlow<Map<UUID, Movie>>

View File

@@ -1,7 +1,7 @@
package hu.bbara.purefin.data package hu.bbara.purefin.data
import java.util.UUID
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import java.util.UUID
interface SmartDownloadStore { interface SmartDownloadStore {
suspend fun enable(seriesId: UUID) 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 kotlinx.coroutines.flow.Flow
import java.util.UUID
interface UserSessionRepository { interface UserSessionRepository {
val serverUrl: Flow<String> val serverUrl: Flow<String>

View File

@@ -5,7 +5,7 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import hu.bbara.purefin.data.HomeRepository import hu.bbara.purefin.data.HomeRepository
import hu.bbara.purefin.data.MediaCatalogReader 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.download.MediaDownloadController
import hu.bbara.purefin.model.LibraryKind import hu.bbara.purefin.model.LibraryKind
import hu.bbara.purefin.model.Media 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.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel 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.download.MediaDownloadController
import hu.bbara.purefin.image.ArtworkKind import hu.bbara.purefin.image.ArtworkKind
import hu.bbara.purefin.image.ImageUrlBuilder import hu.bbara.purefin.image.ImageUrlBuilder
@@ -22,7 +23,7 @@ import javax.inject.Inject
@HiltViewModel @HiltViewModel
class DownloadsViewModel @Inject constructor( class DownloadsViewModel @Inject constructor(
private val offlineCatalogReader: OfflineCatalogReader, @Offline private val offlineCatalogReader: MediaRepository,
private val navigationManager: NavigationManager, private val navigationManager: NavigationManager,
private val downloadManager: MediaDownloadController, private val downloadManager: MediaDownloadController,
) : ViewModel() { ) : ViewModel() {

View File

@@ -4,7 +4,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import hu.bbara.purefin.data.AuthenticationRepository 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.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow

View File

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

View File

@@ -1,6 +1,6 @@
package hu.bbara.purefin.jellyfin 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.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob

View File

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

View File

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

View File

@@ -30,6 +30,7 @@ kotlin {
dependencies { dependencies {
implementation(project(":core-model")) implementation(project(":core-model"))
implementation(project(":core"))
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

@@ -4,7 +4,7 @@ import android.util.Log
import androidx.datastore.core.DataStore import androidx.datastore.core.DataStore
import hu.bbara.purefin.data.HomeRepository import hu.bbara.purefin.data.HomeRepository
import hu.bbara.purefin.data.NetworkMonitor 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.ArtworkKind
import hu.bbara.purefin.image.ImageUrlBuilder import hu.bbara.purefin.image.ImageUrlBuilder
import hu.bbara.purefin.model.Episode import hu.bbara.purefin.model.Episode

View File

@@ -1,21 +1,13 @@
package hu.bbara.purefin.data.catalog package hu.bbara.purefin.data.catalog
import hu.bbara.purefin.data.MediaCatalogReader import hu.bbara.purefin.data.MediaRepository
import hu.bbara.purefin.data.MediaProgressWriter import hu.bbara.purefin.data.UserSessionRepository
import hu.bbara.purefin.data.jellyfin.client.JellyfinApiClient import hu.bbara.purefin.data.jellyfin.client.JellyfinApiClient
import hu.bbara.purefin.image.ImageUrlBuilder import hu.bbara.purefin.image.ImageUrlBuilder
import hu.bbara.purefin.data.session.UserSessionRepository
import hu.bbara.purefin.model.Episode import hu.bbara.purefin.model.Episode
import hu.bbara.purefin.model.Movie import hu.bbara.purefin.model.Movie
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 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.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
@@ -28,12 +20,19 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.jellyfin.sdk.model.api.BaseItemDto 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 @Singleton
class InMemoryMediaRepository @Inject constructor( class InMemoryMediaRepository @Inject constructor(
private val userSessionRepository: UserSessionRepository, private val userSessionRepository: UserSessionRepository,
private val jellyfinApiClient: JellyfinApiClient, private val jellyfinApiClient: JellyfinApiClient,
) : MediaCatalogReader, MediaProgressWriter { ) : MediaRepository {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO) private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)

View File

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

View File

@@ -5,7 +5,7 @@ import android.util.Log
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import hu.bbara.purefin.data.PlaybackMethod import hu.bbara.purefin.data.PlaybackMethod
import hu.bbara.purefin.data.PlaybackReportContext 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.Dispatchers
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withContext 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.EpisodeDownloadSource
import hu.bbara.purefin.data.MovieDownloadSource import hu.bbara.purefin.data.MovieDownloadSource
import hu.bbara.purefin.data.PlaybackMethod 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.client.JellyfinApiClient
import hu.bbara.purefin.data.jellyfin.playback.PlaybackDecisionResolver import hu.bbara.purefin.data.jellyfin.playback.PlaybackDecisionResolver
import hu.bbara.purefin.data.jellyfin.playback.playbackCustomCacheKey import hu.bbara.purefin.data.jellyfin.playback.playbackCustomCacheKey

View File

@@ -1,7 +1,7 @@
package hu.bbara.purefin.data.jellyfin.playback package hu.bbara.purefin.data.jellyfin.playback
import android.util.Log 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 hu.bbara.purefin.data.jellyfin.client.JellyfinApiClient
import java.util.UUID import java.util.UUID
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap

View File

@@ -2,7 +2,7 @@ package hu.bbara.purefin.data.jellyfin.session
import android.util.Log import android.util.Log
import hu.bbara.purefin.data.AuthenticationRepository 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 hu.bbara.purefin.data.jellyfin.client.JellyfinApiClient
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton

View File

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

View File

@@ -1,7 +1,7 @@
package hu.bbara.purefin.data.jellyfin.session package hu.bbara.purefin.data.jellyfin.session
import androidx.datastore.core.DataStore 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.Flow
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first

View File

@@ -4,7 +4,12 @@ import dagger.Binds
import dagger.Module import dagger.Module
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent 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 import hu.bbara.purefin.data.catalog.OfflineMediaRepository
@Module @Module
@@ -12,5 +17,13 @@ import hu.bbara.purefin.data.catalog.OfflineMediaRepository
abstract class MediaRepositoryModule { abstract class MediaRepositoryModule {
@Binds @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
} }