mirror of
https://github.com/bbara04/Purefin.git
synced 2026-07-23 19:26:50 +00:00
feat(search): wire full-screen search with genre browsing
This commit is contained in:
@@ -6,6 +6,7 @@ import hu.bbara.purefin.data.HomeRepository
|
||||
import hu.bbara.purefin.data.NetworkMonitor
|
||||
import hu.bbara.purefin.data.UserSessionRepository
|
||||
import hu.bbara.purefin.data.converter.toEpisode
|
||||
import hu.bbara.purefin.data.converter.toGenre
|
||||
import hu.bbara.purefin.data.converter.toLibrary
|
||||
import hu.bbara.purefin.data.converter.toMovie
|
||||
import hu.bbara.purefin.data.converter.toSeason
|
||||
@@ -103,6 +104,7 @@ class InMemoryAppContentRepository @Inject constructor(
|
||||
loadContinueWatching()
|
||||
loadNextUp()
|
||||
loadLatestLibraryContent()
|
||||
loadGenres()
|
||||
Log.d(TAG, "Home refresh successful")
|
||||
persistHomeCache()
|
||||
}.onFailure { error ->
|
||||
@@ -199,7 +201,7 @@ class InMemoryAppContentRepository @Inject constructor(
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun loadLibraries() {
|
||||
private suspend fun loadLibraries() {
|
||||
val librariesItem = runCatching { jellyfinApiClient.getLibraries() }
|
||||
.getOrElse { error ->
|
||||
Log.w(TAG, "Unable to load libraries", error)
|
||||
@@ -221,7 +223,7 @@ class InMemoryAppContentRepository @Inject constructor(
|
||||
onlineMediaRepository.upsertSeries(series)
|
||||
}
|
||||
|
||||
suspend fun loadLibrary(library: Library): Library {
|
||||
private suspend fun loadLibrary(library: Library): Library {
|
||||
val contentItem = runCatching { jellyfinApiClient.getLibraryContent(library.id) }
|
||||
.getOrElse { error ->
|
||||
Log.w(TAG, "Unable to load library ${library.id}", error)
|
||||
@@ -237,7 +239,7 @@ class InMemoryAppContentRepository @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun loadSuggestions() {
|
||||
private suspend fun loadSuggestions() {
|
||||
val suggestionsItems = runCatching { jellyfinApiClient.getSuggestions() }
|
||||
.getOrElse { error ->
|
||||
Log.w(TAG, "Unable to load suggestions", error)
|
||||
@@ -258,7 +260,7 @@ class InMemoryAppContentRepository @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun loadContinueWatching() {
|
||||
private suspend fun loadContinueWatching() {
|
||||
val continueWatchingItems = runCatching { jellyfinApiClient.getContinueWatching() }
|
||||
.getOrElse { error ->
|
||||
Log.w(TAG, "Unable to load continue watching", error)
|
||||
@@ -279,7 +281,7 @@ class InMemoryAppContentRepository @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun loadNextUp() {
|
||||
private suspend fun loadNextUp() {
|
||||
val nextUpItems = runCatching { jellyfinApiClient.getNextUpEpisodes() }
|
||||
.getOrElse { error ->
|
||||
Log.w(TAG, "Unable to load next up", error)
|
||||
@@ -294,7 +296,7 @@ class InMemoryAppContentRepository @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun loadLatestLibraryContent() {
|
||||
private suspend fun loadLatestLibraryContent() {
|
||||
val librariesItem = runCatching { jellyfinApiClient.getLibraries() }
|
||||
.getOrElse { error ->
|
||||
Log.w(TAG, "Unable to load latest library content", error)
|
||||
@@ -337,6 +339,12 @@ class InMemoryAppContentRepository @Inject constructor(
|
||||
latestLibraryContentState.value = latestLibraryContents
|
||||
}
|
||||
|
||||
private suspend fun loadGenres() {
|
||||
val baseItemDtos = jellyfinApiClient.getGenres()
|
||||
val genres = baseItemDtos.map { it.toGenre() }
|
||||
onlineMediaRepository.upsertGenres(genres.toSet())
|
||||
}
|
||||
|
||||
private suspend fun serverUrl(): String {
|
||||
return userSessionRepository.serverUrl.first()
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import hu.bbara.purefin.data.converter.toSeason
|
||||
import hu.bbara.purefin.data.converter.toSeries
|
||||
import hu.bbara.purefin.data.jellyfin.client.JellyfinApiClient
|
||||
import hu.bbara.purefin.model.Episode
|
||||
import hu.bbara.purefin.model.Genre
|
||||
import hu.bbara.purefin.model.Movie
|
||||
import hu.bbara.purefin.model.Series
|
||||
import kotlinx.coroutines.CancellationException
|
||||
@@ -48,6 +49,9 @@ class InMemoryMediaRepository @Inject constructor(
|
||||
private val episodesState = MutableStateFlow<Map<UUID, Episode>>(emptyMap())
|
||||
override val episodes: StateFlow<Map<UUID, Episode>> = episodesState.asStateFlow()
|
||||
|
||||
private val genresState = MutableStateFlow<Set<Genre>>(emptySet())
|
||||
override var genres: StateFlow<Set<Genre>> = genresState.asStateFlow()
|
||||
|
||||
override suspend fun getMovie(id: UUID): Flow<Movie?> {
|
||||
if (!moviesState.value.containsKey(id)) {
|
||||
jellyfinApiClient.getItemInfo(id)?.let { item ->
|
||||
@@ -92,6 +96,10 @@ class InMemoryMediaRepository @Inject constructor(
|
||||
return episodesState.map { it[id] }
|
||||
}
|
||||
|
||||
fun upsertGenres(genres: Set<Genre>) {
|
||||
genresState.update { current -> current + genres }
|
||||
}
|
||||
|
||||
fun upsertMovies(movies: List<Movie>) {
|
||||
moviesState.update { current -> current + movies.associateBy { it.id } }
|
||||
}
|
||||
|
||||
@@ -3,12 +3,14 @@ package hu.bbara.purefin.data.catalog
|
||||
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.Genre
|
||||
import hu.bbara.purefin.model.Movie
|
||||
import hu.bbara.purefin.model.Series
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
@@ -32,6 +34,8 @@ class OfflineMediaRepository @Inject constructor(
|
||||
override val episodes: StateFlow<Map<UUID, Episode>> = localDataSource.episodesFlow
|
||||
.stateIn(scope, SharingStarted.Eagerly, emptyMap())
|
||||
|
||||
override var genres: StateFlow<Set<Genre>> = MutableStateFlow(emptySet())
|
||||
|
||||
override suspend fun getMovie(id: UUID): Flow<Movie?> {
|
||||
return movies.map { it[id] }
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package hu.bbara.purefin.data.converter
|
||||
import hu.bbara.purefin.image.ArtworkKind
|
||||
import hu.bbara.purefin.image.ImageUrlBuilder
|
||||
import hu.bbara.purefin.model.Episode
|
||||
import hu.bbara.purefin.model.Genre
|
||||
import hu.bbara.purefin.model.Library
|
||||
import hu.bbara.purefin.model.LibraryKind
|
||||
import hu.bbara.purefin.model.Movie
|
||||
@@ -112,6 +113,12 @@ fun BaseItemDto.toEpisode(serverUrl: String): Episode {
|
||||
)
|
||||
}
|
||||
|
||||
fun BaseItemDto.toGenre() : Genre {
|
||||
return Genre(
|
||||
name = name ?: "Unknown"
|
||||
)
|
||||
}
|
||||
|
||||
fun formatReleaseDate(date: LocalDateTime?, fallbackYear: Int?): String {
|
||||
if (date == null) {
|
||||
return fallbackYear?.toString() ?: "—"
|
||||
|
||||
Reference in New Issue
Block a user