mirror of
https://github.com/bbara04/Purefin.git
synced 2026-07-23 19:26:50 +00:00
revert(data): remove ETag caching and head-fetch home refresh
Reverts5491c38(ETag-based conditional HTTP caching for home refresh) and1ec9ff9(head-fetch rows and count-only libraries). Restores the pre-ETag home refresh path that fully loads library content per library and fetches each home row in a single request. Preserves unrelated later improvements: SingleFlight deduplication (86f44ac), nullable toLibrary skip for unsupported library types (80b1bd8), and upsert-before-publish ordering to prevent empty intermediate states (f0a7828).
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
package hu.bbara.purefin.core.data
|
||||
|
||||
import hu.bbara.purefin.core.model.MediaUiModel
|
||||
import hu.bbara.purefin.model.Library
|
||||
import hu.bbara.purefin.model.Media
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
@@ -14,15 +13,4 @@ interface HomeRepository {
|
||||
val latestLibraryContent: StateFlow<Map<UUID, List<Media>>>
|
||||
fun ensureReady()
|
||||
suspend fun refreshHomeData()
|
||||
|
||||
/**
|
||||
* Fetches the full content (movies or series) of a single library on
|
||||
* demand. Used by the library detail screen; the home page no longer
|
||||
* pays for full library content on every refresh.
|
||||
*
|
||||
* Returns `null` when the server returned 304 Not Modified for the
|
||||
* per-library ETag — the caller should keep its previously fetched
|
||||
* copy. An empty list is a legitimate "the library is empty" result.
|
||||
*/
|
||||
suspend fun loadLibraryContent(libraryId: UUID): List<MediaUiModel>?
|
||||
}
|
||||
|
||||
@@ -68,17 +68,16 @@ class AppViewModel @Inject constructor(
|
||||
|
||||
val libraries = homeRepository.libraries.map { libraries ->
|
||||
libraries.map {
|
||||
// The home page no longer fetches the full library content
|
||||
// (see InMemoryAppContentRepository.loadLibraries). isEmpty
|
||||
// therefore reflects the actual server-reported size, not
|
||||
// the contents of the local media repository.
|
||||
LibraryUiModel(
|
||||
id = it.id,
|
||||
name = it.name,
|
||||
type = it.type,
|
||||
posterUrl = it.posterUrl,
|
||||
size = it.size,
|
||||
isEmpty = it.size == 0,
|
||||
isEmpty = when (it.type) {
|
||||
LibraryKind.MOVIES -> localMediaRepository.movies.value.isEmpty()
|
||||
LibraryKind.SERIES -> localMediaRepository.series.value.isEmpty()
|
||||
}
|
||||
)
|
||||
}
|
||||
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), emptyList())
|
||||
|
||||
@@ -6,13 +6,18 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import hu.bbara.purefin.core.data.HomeRepository
|
||||
import hu.bbara.purefin.core.data.MediaMetadataUpdater
|
||||
import hu.bbara.purefin.core.model.MediaUiModel
|
||||
import hu.bbara.purefin.core.model.MovieUiModel
|
||||
import hu.bbara.purefin.core.model.SeriesUiModel
|
||||
import hu.bbara.purefin.core.navigation.MovieDto
|
||||
import hu.bbara.purefin.core.navigation.NavigationManager
|
||||
import hu.bbara.purefin.core.navigation.Route
|
||||
import hu.bbara.purefin.core.navigation.SeriesDto
|
||||
import hu.bbara.purefin.model.LibraryKind
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
@@ -26,35 +31,24 @@ class LibraryViewModel @Inject constructor(
|
||||
|
||||
private val selectedLibrary = MutableStateFlow<UUID?>(null)
|
||||
|
||||
// Local cache of the last-fetched content per library. Used to preserve
|
||||
// content when re-selecting a library whose ETag matches (so the
|
||||
// repository's 304 response can be treated as "use the cached copy").
|
||||
private val cachedContents = mutableMapOf<UUID, List<MediaUiModel>>()
|
||||
|
||||
private val _contents = MutableStateFlow<List<MediaUiModel>>(emptyList())
|
||||
val contents: StateFlow<List<MediaUiModel>> = _contents.asStateFlow()
|
||||
val contents: StateFlow<List<MediaUiModel>> = combine(selectedLibrary, homeRepository.libraries) {
|
||||
libraryId, libraries ->
|
||||
if (libraryId == null) {
|
||||
return@combine emptyList()
|
||||
}
|
||||
val library = libraries.find { it.id == libraryId } ?: return@combine emptyList()
|
||||
when (library.type) {
|
||||
LibraryKind.SERIES -> library.series!!.map { series ->
|
||||
SeriesUiModel(series)
|
||||
}
|
||||
LibraryKind.MOVIES -> library.movies!!.map { movie ->
|
||||
MovieUiModel(movie)
|
||||
}
|
||||
}
|
||||
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), emptyList())
|
||||
|
||||
init {
|
||||
viewModelScope.launch { homeRepository.ensureReady() }
|
||||
viewModelScope.launch {
|
||||
selectedLibrary.collect { libraryId ->
|
||||
if (libraryId == null) {
|
||||
_contents.value = emptyList()
|
||||
} else {
|
||||
val fresh = homeRepository.loadLibraryContent(libraryId)
|
||||
if (fresh != null) {
|
||||
cachedContents[libraryId] = fresh
|
||||
_contents.value = fresh
|
||||
} else {
|
||||
// ETag 304 — keep the cached copy for this library if
|
||||
// we have one. On a first-visit 304 (rare, would
|
||||
// require the library's ETag to be set without any
|
||||
// prior fetch) the screen briefly shows empty.
|
||||
_contents.value = cachedContents[libraryId] ?: emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onMovieSelected(movieId: UUID) {
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
package hu.bbara.purefin.core.jellyfin
|
||||
|
||||
import javax.inject.Qualifier
|
||||
|
||||
/**
|
||||
* Marks an `OkHttpClient` that is wired into the Jellyfin SDK's `OkHttpFactory`.
|
||||
* Distinct from the unqualified client used for image loading and media streaming
|
||||
* because the SDK has its own auth path and the ETag interceptor should not leak
|
||||
* into non-SDK HTTP calls.
|
||||
*/
|
||||
@Qualifier
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class JellyfinSdkClient
|
||||
Reference in New Issue
Block a user