diff --git a/app/src/main/java/hu/bbara/purefin/app/HomePageViewModel.kt b/app/src/main/java/hu/bbara/purefin/app/HomePageViewModel.kt index 2378f78..a695c80 100644 --- a/app/src/main/java/hu/bbara/purefin/app/HomePageViewModel.kt +++ b/app/src/main/java/hu/bbara/purefin/app/HomePageViewModel.kt @@ -26,19 +26,21 @@ class HomePageViewModel @Inject constructor( private val jellyfinApiClient: JellyfinApiClient ) : ViewModel() { - init { - loadHomePageData() - } - private val _continueWatching = MutableStateFlow>(emptyList()) val continueWatching = _continueWatching.asStateFlow() private val _libraries = MutableStateFlow>(emptyList()) val libraries = _libraries.asStateFlow() - private val _libraryContent = MutableStateFlow>>(emptyMap()) - val libraryContent = _libraryContent.asStateFlow() + private val _libraryItems = MutableStateFlow>>(emptyMap()) + val libraryItems = _libraryItems.asStateFlow() + private val _latestLibraryContent = MutableStateFlow>>(emptyMap()) + val latestLibraryContent = _latestLibraryContent.asStateFlow() + + init { + loadHomePageData() + } fun loadContinueWatching() { viewModelScope.launch { @@ -68,34 +70,84 @@ class HomePageViewModel @Inject constructor( fun loadLibraries() { viewModelScope.launch { - val libraries: List = jellyfinApiClient.getLibraries() - val mappedLibraries = libraries.map { - LibraryItem( - name = it.name!!, - id = it.id - ) + loadLibrariesInternal() + } + } + + private suspend fun loadLibrariesInternal() { + val libraries: List = jellyfinApiClient.getLibraries() + val mappedLibraries = libraries.map { + LibraryItem( + name = it.name!!, + id = it.id + ) + } + _libraries.value = mappedLibraries + } + + fun loadAllLibraryItems() { + viewModelScope.launch { + if (_libraries.value.isEmpty()) { + loadLibrariesInternal() } - _libraries.value = mappedLibraries - mappedLibraries.forEach { library -> - loadLibrary(library.id) + _libraries.value.forEach { library -> + loadLibraryItems(library.id) } } } - fun loadLibrary(libraryId: UUID) { - if (_libraryContent.value.containsKey(libraryId)) return + private fun loadLibraryItems(libraryId: UUID) { viewModelScope.launch { - val libraryItems = jellyfinApiClient.getLibrary(libraryId) - val posterItems = libraryItems.map { + val libraryItems: List = jellyfinApiClient.getLibrary(libraryId) + val libraryPosterItems = libraryItems.map { PosterItem( id = it.id, - title = it.name ?: "Unknown", - colors = listOf(Color.Blue, Color.Cyan), - isLatest = false + title = it.name ?: "Unknown" ) } - _libraryContent.update { currentMap -> - currentMap + (libraryId to posterItems) + _libraryItems.update { currentMap -> + currentMap + (libraryId to libraryPosterItems) + } + } + } + + fun loadAllShownLibraryItems() { + viewModelScope.launch { + if (_libraries.value.isEmpty()) { + loadLibrariesInternal() + } + _libraries.value.forEach { library -> + loadLatestLibraryItems(library.id) + } + } + } + + + fun loadLatestLibraryItems(libraryId: UUID) { + if (_libraryItems.value.containsKey(libraryId)) return + val libraryItems = _libraryItems.value[libraryId] + viewModelScope.launch { + val latestLibraryItems = jellyfinApiClient.getLatestFromLibrary(libraryId) + val latestLibraryPosterItem = latestLibraryItems.mapNotNull { + when (it.type) { + BaseItemKind.MOVIE -> PosterItem( + id = it.id, + title = it.name ?: "Unknown" + ) + BaseItemKind.EPISODE -> PosterItem( + id = it.seriesId!!, + title = it.seriesName ?: "Unknown" + ) + + BaseItemKind.SEASON -> PosterItem( + id = it.seriesId!!, + title = it.seriesName ?: "Unknown" + ) + else -> null + } + } + _latestLibraryContent.update { currentMap -> + currentMap + (libraryId to latestLibraryPosterItem) } } } @@ -103,6 +155,8 @@ class HomePageViewModel @Inject constructor( fun loadHomePageData() { loadContinueWatching() loadLibraries() + loadAllLibraryItems() + loadAllShownLibraryItems() } fun logout() { diff --git a/app/src/main/java/hu/bbara/purefin/app/home/HomeContent.kt b/app/src/main/java/hu/bbara/purefin/app/home/HomeContent.kt index 32ce8d0..86d40b1 100644 --- a/app/src/main/java/hu/bbara/purefin/app/home/HomeContent.kt +++ b/app/src/main/java/hu/bbara/purefin/app/home/HomeContent.kt @@ -23,7 +23,7 @@ fun HomeContent( ) { val libraries by viewModel.libraries.collectAsState() - val libraryContent by viewModel.libraryContent.collectAsState() + val libraryContent by viewModel.latestLibraryContent.collectAsState() LazyColumn( modifier = modifier diff --git a/app/src/main/java/hu/bbara/purefin/app/home/HomeModels.kt b/app/src/main/java/hu/bbara/purefin/app/home/HomeModels.kt index 37cd8e8..f19d366 100644 --- a/app/src/main/java/hu/bbara/purefin/app/home/HomeModels.kt +++ b/app/src/main/java/hu/bbara/purefin/app/home/HomeModels.kt @@ -19,9 +19,7 @@ data class LibraryItem( data class PosterItem( val id: UUID, - val title: String, - val isLatest: Boolean, - val colors: List + val title: String ) data class HomeNavItem( diff --git a/app/src/main/java/hu/bbara/purefin/client/JellyfinApiClient.kt b/app/src/main/java/hu/bbara/purefin/client/JellyfinApiClient.kt index 9113015..cd2ae05 100644 --- a/app/src/main/java/hu/bbara/purefin/client/JellyfinApiClient.kt +++ b/app/src/main/java/hu/bbara/purefin/client/JellyfinApiClient.kt @@ -10,6 +10,7 @@ import org.jellyfin.sdk.api.client.extensions.authenticateUserByName import org.jellyfin.sdk.api.client.extensions.itemsApi import org.jellyfin.sdk.api.client.extensions.libraryApi import org.jellyfin.sdk.api.client.extensions.userApi +import org.jellyfin.sdk.api.client.extensions.userLibraryApi import org.jellyfin.sdk.createJellyfin import org.jellyfin.sdk.model.ClientInfo import org.jellyfin.sdk.model.api.BaseItemDto @@ -115,4 +116,24 @@ class JellyfinApiClient @Inject constructor( return response.content.items } + /** + * Fetches the latest media items from a specified library including Movie, Episode, Season. + * + * @param libraryId The UUID of the library to fetch from + * @return A list of [BaseItemDto] representing the latest media items that includes Movie, Episode, Season, or an empty list if not configured + */ + suspend fun getLatestFromLibrary(libraryId: UUID): List { + if (!ensureConfigured()) { + return emptyList() + } + val response = api.userLibraryApi.getLatestMedia( + userId = getUserId(), + parentId = libraryId, + includeItemTypes = listOf(BaseItemKind.MOVIE, BaseItemKind.EPISODE, BaseItemKind.SEASON), + limit = 10 + ) + Log.d("getLatestFromLibrary response: {}", response.content.toString()) + return response.content + } + }