From cca271e818a0a1c8c93e23aafa892d2f795845a2 Mon Sep 17 00:00:00 2001 From: Damontecres Date: Thu, 12 Feb 2026 20:38:04 -0500 Subject: [PATCH 1/2] Integrate nav drawer settings for default home page --- .../wholphin/data/NavDrawerItemRepository.kt | 97 ------------------- .../wholphin/services/HomeSettingsService.kt | 34 +++---- .../wholphin/services/NavDrawerService.kt | 25 +++++ .../wholphin/ui/main/HomeViewModel.kt | 17 +--- .../ui/main/settings/HomeSettingsViewModel.kt | 20 ++-- .../damontecres/wholphin/ui/nav/NavDrawer.kt | 10 +- .../ui/preferences/PreferencesViewModel.kt | 5 - 7 files changed, 56 insertions(+), 152 deletions(-) delete mode 100644 app/src/main/java/com/github/damontecres/wholphin/data/NavDrawerItemRepository.kt diff --git a/app/src/main/java/com/github/damontecres/wholphin/data/NavDrawerItemRepository.kt b/app/src/main/java/com/github/damontecres/wholphin/data/NavDrawerItemRepository.kt deleted file mode 100644 index 2312c62c7..000000000 --- a/app/src/main/java/com/github/damontecres/wholphin/data/NavDrawerItemRepository.kt +++ /dev/null @@ -1,97 +0,0 @@ -package com.github.damontecres.wholphin.data - -import android.content.Context -import com.github.damontecres.wholphin.data.model.BaseItem -import com.github.damontecres.wholphin.data.model.NavDrawerPinnedItem -import com.github.damontecres.wholphin.data.model.NavPinType -import com.github.damontecres.wholphin.services.SeerrServerRepository -import com.github.damontecres.wholphin.ui.nav.Destination -import com.github.damontecres.wholphin.ui.nav.NavDrawerItem -import com.github.damontecres.wholphin.ui.nav.ServerNavDrawerItem -import com.github.damontecres.wholphin.util.supportedCollectionTypes -import dagger.hilt.android.qualifiers.ApplicationContext -import kotlinx.coroutines.flow.first -import org.jellyfin.sdk.api.client.ApiClient -import org.jellyfin.sdk.api.client.extensions.liveTvApi -import org.jellyfin.sdk.api.client.extensions.userViewsApi -import org.jellyfin.sdk.model.api.CollectionType -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class NavDrawerItemRepository - @Inject - constructor( - @param:ApplicationContext private val context: Context, - private val api: ApiClient, - private val serverRepository: ServerRepository, - private val serverPreferencesDao: ServerPreferencesDao, - private val seerrServerRepository: SeerrServerRepository, - ) { - suspend fun getNavDrawerItems(): List { - val user = serverRepository.currentUser.value - val tvAccess = - serverRepository.currentUserDto.value - ?.policy - ?.enableLiveTvAccess ?: false - val userViews = - api.userViewsApi - .getUserViews(userId = user?.id) - .content.items - val recordingFolders = - if (tvAccess) { - api.liveTvApi - .getRecordingFolders(userId = user?.id) - .content.items - .map { it.id } - .toSet() - } else { - setOf() - } - - val builtins = - if (seerrServerRepository.active.first()) { - listOf(NavDrawerItem.Favorites, NavDrawerItem.Discover) - } else { - listOf(NavDrawerItem.Favorites) - } - - val libraries = - userViews - .filter { it.collectionType in supportedCollectionTypes || it.id in recordingFolders } - .map { - val destination = - if (it.id in recordingFolders) { - Destination.Recordings(it.id) - } else { - BaseItem.from(it, api).destination() - } - ServerNavDrawerItem( - itemId = it.id, - name = it.name ?: it.id.toString(), - destination = destination, - type = it.collectionType ?: CollectionType.UNKNOWN, - ) - } - return builtins + libraries - } - - suspend fun getFilteredNavDrawerItems(items: List): List { - val user = serverRepository.currentUser.value - val navDrawerPins = - user - ?.let { - serverPreferencesDao.getNavDrawerPinnedItems(it) - }.orEmpty() - val filtered = items.filter { navDrawerPins.isPinned(it.id) } - if (items.size != filtered.size) { - // Some were filtered out, check if should include More - if (navDrawerPins.isPinned(NavDrawerItem.More.id)) { - return filtered + listOf(NavDrawerItem.More) - } - } - return filtered - } - } - -fun List.isPinned(id: String) = (firstOrNull { it.itemId == id }?.type ?: NavPinType.PINNED) == NavPinType.PINNED diff --git a/app/src/main/java/com/github/damontecres/wholphin/services/HomeSettingsService.kt b/app/src/main/java/com/github/damontecres/wholphin/services/HomeSettingsService.kt index a868692a2..083d461d5 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/services/HomeSettingsService.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/services/HomeSettingsService.kt @@ -2,7 +2,7 @@ package com.github.damontecres.wholphin.services import android.content.Context import com.github.damontecres.wholphin.R -import com.github.damontecres.wholphin.data.NavDrawerItemRepository +import com.github.damontecres.wholphin.data.ServerRepository import com.github.damontecres.wholphin.data.model.BaseItem import com.github.damontecres.wholphin.data.model.HomePageSettings import com.github.damontecres.wholphin.data.model.HomeRowConfig @@ -12,8 +12,8 @@ import com.github.damontecres.wholphin.preferences.HomePagePreferences import com.github.damontecres.wholphin.ui.DefaultItemFields import com.github.damontecres.wholphin.ui.SlimItemFields import com.github.damontecres.wholphin.ui.components.getGenreImageMap +import com.github.damontecres.wholphin.ui.isNotNullOrBlank import com.github.damontecres.wholphin.ui.main.settings.Library -import com.github.damontecres.wholphin.ui.nav.ServerNavDrawerItem import com.github.damontecres.wholphin.ui.toServerString import com.github.damontecres.wholphin.util.GetGenresRequestHandler import com.github.damontecres.wholphin.util.GetItemsRequestHandler @@ -64,8 +64,9 @@ class HomeSettingsService constructor( @param:ApplicationContext private val context: Context, private val api: ApiClient, + private val serverRepository: ServerRepository, private val userPreferencesService: UserPreferencesService, - private val navDrawerItemRepository: NavDrawerItemRepository, + private val navDrawerService: NavDrawerService, private val latestNextUpService: LatestNextUpService, private val imageUrlService: ImageUrlService, private val suggestionService: SuggestionService, @@ -233,7 +234,7 @@ class HomeSettingsService } HomePageResolvedSettings(resolvedRows) } else { - createDefault() + createDefault(userId) } currentSettings.update { resolvedSettings } @@ -251,25 +252,24 @@ class HomeSettingsService /** * Create a default [HomePageResolvedSettings] using the available libraries */ - suspend fun createDefault(): HomePageResolvedSettings { + suspend fun createDefault(userId: UUID): HomePageResolvedSettings { Timber.v("Creating default settings") - val navDrawerItems = navDrawerItemRepository.getNavDrawerItems() + val user = serverRepository.currentUser.value?.takeIf { it.id == userId } val libraries = - navDrawerItems - .filter { it is ServerNavDrawerItem } - .map { - it as ServerNavDrawerItem - Library(it.itemId, it.name, it.type) - } + if (user != null) { + navDrawerService.getFilteredUserLibraries(user) + } else { + navDrawerService.getAllUserLibraries(userId) + } + val prefs = userPreferencesService.getCurrent().appPreferences.homePagePreferences + val includedIds = - navDrawerItemRepository - .getFilteredNavDrawerItems(navDrawerItems) - .filter { it is ServerNavDrawerItem } + libraries .mapIndexed { index, it -> - val parentId = (it as ServerNavDrawerItem).itemId - val name = libraries.firstOrNull { it.itemId == parentId }?.name + val parentId = it.itemId + val name = it.name.takeIf { it.isNotNullOrBlank() } val title = name?.let { context.getString(R.string.recently_added_in, it) } ?: context.getString(R.string.recently_added) diff --git a/app/src/main/java/com/github/damontecres/wholphin/services/NavDrawerService.kt b/app/src/main/java/com/github/damontecres/wholphin/services/NavDrawerService.kt index 785eb6768..fbce042c9 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/services/NavDrawerService.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/services/NavDrawerService.kt @@ -8,6 +8,7 @@ import com.github.damontecres.wholphin.data.model.BaseItem import com.github.damontecres.wholphin.data.model.JellyfinUser import com.github.damontecres.wholphin.data.model.NavPinType import com.github.damontecres.wholphin.services.hilt.DefaultCoroutineScope +import com.github.damontecres.wholphin.ui.main.settings.Library import com.github.damontecres.wholphin.ui.nav.Destination import com.github.damontecres.wholphin.ui.nav.NavDrawerItem import com.github.damontecres.wholphin.ui.nav.ServerNavDrawerItem @@ -26,6 +27,7 @@ import org.jellyfin.sdk.api.client.extensions.userViewsApi import org.jellyfin.sdk.model.api.CollectionType import org.jellyfin.sdk.model.api.UserDto import timber.log.Timber +import java.util.UUID import javax.inject.Inject import javax.inject.Singleton @@ -66,6 +68,29 @@ class NavDrawerService }.launchIn(coroutineScope) } + suspend fun getAllUserLibraries(userId: UUID): List { + val userViews = + api.userViewsApi + .getUserViews(userId = userId) + .content.items + val libraries = + userViews + .filter { it.collectionType in supportedCollectionTypes } + .map { Library(it.id, it.name ?: "", it.collectionType ?: CollectionType.UNKNOWN) } + return libraries + } + + suspend fun getFilteredUserLibraries(user: JellyfinUser): List { + val pins = + serverPreferencesDao + .getNavDrawerPinnedItems(user) + .associateBy { it.itemId } + val libraries = + getAllUserLibraries(user.id) + .filterNot { pins[ServerNavDrawerItem.getId(it.itemId)]?.type == NavPinType.UNPINNED } + return libraries + } + suspend fun updateNavDrawer( user: JellyfinUser, userDto: UserDto, diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomeViewModel.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomeViewModel.kt index 7ee229024..1e72830f5 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomeViewModel.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomeViewModel.kt @@ -3,7 +3,6 @@ package com.github.damontecres.wholphin.ui.main import android.content.Context import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.github.damontecres.wholphin.data.NavDrawerItemRepository import com.github.damontecres.wholphin.data.ServerRepository import com.github.damontecres.wholphin.data.model.BaseItem import com.github.damontecres.wholphin.data.model.HomeRowConfig @@ -13,11 +12,10 @@ import com.github.damontecres.wholphin.services.FavoriteWatchManager import com.github.damontecres.wholphin.services.HomePageResolvedSettings import com.github.damontecres.wholphin.services.HomeSettingsService import com.github.damontecres.wholphin.services.MediaReportService +import com.github.damontecres.wholphin.services.NavDrawerService import com.github.damontecres.wholphin.services.NavigationManager import com.github.damontecres.wholphin.services.UserPreferencesService import com.github.damontecres.wholphin.ui.launchIO -import com.github.damontecres.wholphin.ui.main.settings.Library -import com.github.damontecres.wholphin.ui.nav.ServerNavDrawerItem import com.github.damontecres.wholphin.ui.showToast import com.github.damontecres.wholphin.util.ExceptionHandler import com.github.damontecres.wholphin.util.HomeRowLoadingState @@ -46,8 +44,8 @@ class HomeViewModel @param:ApplicationContext private val context: Context, val navigationManager: NavigationManager, val serverRepository: ServerRepository, - val navDrawerItemRepository: NavDrawerItemRepository, val mediaReportService: MediaReportService, + private val navDrawerService: NavDrawerService, private val homeSettingsService: HomeSettingsService, private val favoriteWatchManager: FavoriteWatchManager, private val datePlayedService: DatePlayedService, @@ -69,17 +67,8 @@ class HomeViewModel val preferences = userPreferencesService.getCurrent() val prefs = preferences.appPreferences.homePagePreferences - val navDrawerItems = - navDrawerItemRepository - .getNavDrawerItems() - val libraries = - navDrawerItems - .filter { it is ServerNavDrawerItem } - .map { - it as ServerNavDrawerItem - Library(it.itemId, it.name, it.type) - } serverRepository.currentUserDto.value?.let { userDto -> + val libraries = navDrawerService.getAllUserLibraries(userDto.id) val settings = homeSettingsService.currentSettings.first { it != HomePageResolvedSettings.EMPTY } val state = state.value diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeSettingsViewModel.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeSettingsViewModel.kt index 3a5f088a4..53c457ff9 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeSettingsViewModel.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeSettingsViewModel.kt @@ -7,7 +7,6 @@ import androidx.datastore.core.DataStore import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.github.damontecres.wholphin.R -import com.github.damontecres.wholphin.data.NavDrawerItemRepository import com.github.damontecres.wholphin.data.ServerRepository import com.github.damontecres.wholphin.data.model.BaseItem import com.github.damontecres.wholphin.data.model.HomePageSettings @@ -26,12 +25,12 @@ import com.github.damontecres.wholphin.services.BackdropService import com.github.damontecres.wholphin.services.HomePageResolvedSettings import com.github.damontecres.wholphin.services.HomeRowConfigDisplay import com.github.damontecres.wholphin.services.HomeSettingsService +import com.github.damontecres.wholphin.services.NavDrawerService import com.github.damontecres.wholphin.services.SeerrServerRepository import com.github.damontecres.wholphin.services.UnsupportedHomeSettingsVersionException import com.github.damontecres.wholphin.services.UserPreferencesService import com.github.damontecres.wholphin.services.hilt.IoCoroutineScope import com.github.damontecres.wholphin.ui.launchIO -import com.github.damontecres.wholphin.ui.nav.ServerNavDrawerItem import com.github.damontecres.wholphin.ui.showToast import com.github.damontecres.wholphin.util.HomeRowLoadingState import com.github.damontecres.wholphin.util.LoadingState @@ -68,7 +67,7 @@ class HomeSettingsViewModel private val homeSettingsService: HomeSettingsService, private val serverRepository: ServerRepository, private val userPreferencesService: UserPreferencesService, - private val navDrawerItemRepository: NavDrawerItemRepository, + private val navDrawerService: NavDrawerService, private val backdropService: BackdropService, private val seerrServerRepository: SeerrServerRepository, val preferencesDataStore: DataStore, @@ -84,16 +83,8 @@ class HomeSettingsViewModel init { addCloseable { saveToLocal() } viewModelScope.launchIO { - val navDrawerItems = - navDrawerItemRepository - .getNavDrawerItems() - val libraries = - navDrawerItems - .filter { it is ServerNavDrawerItem } - .map { - it as ServerNavDrawerItem - Library(it.itemId, it.name, it.type) - } + val userId = serverRepository.currentUser.value?.id ?: return@launchIO + val libraries = navDrawerService.getAllUserLibraries(userId) val currentSettings = homeSettingsService.currentSettings.first { it != HomePageResolvedSettings.EMPTY } Timber.v("currentSettings=%s", currentSettings) @@ -525,8 +516,9 @@ class HomeSettingsViewModel fun resetToDefault() { viewModelScope.launchIO { + val userId = serverRepository.currentUser.value?.id ?: return@launchIO _state.update { it.copy(loading = LoadingState.Loading) } - val result = homeSettingsService.createDefault() + val result = homeSettingsService.createDefault(userId) _state.update { it.copy(rows = result.rows) } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/nav/NavDrawer.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/nav/NavDrawer.kt index f1c436189..3527a95ea 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/nav/NavDrawer.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/nav/NavDrawer.kt @@ -65,7 +65,6 @@ import androidx.tv.material3.ProvideTextStyle import androidx.tv.material3.Text import androidx.tv.material3.surfaceColorAtElevation import com.github.damontecres.wholphin.R -import com.github.damontecres.wholphin.data.NavDrawerItemRepository import com.github.damontecres.wholphin.data.model.JellyfinServer import com.github.damontecres.wholphin.data.model.JellyfinUser import com.github.damontecres.wholphin.preferences.AppThemeColors @@ -73,7 +72,6 @@ import com.github.damontecres.wholphin.preferences.UserPreferences import com.github.damontecres.wholphin.services.BackdropService import com.github.damontecres.wholphin.services.NavDrawerService import com.github.damontecres.wholphin.services.NavigationManager -import com.github.damontecres.wholphin.services.SeerrServerRepository import com.github.damontecres.wholphin.services.SetupDestination import com.github.damontecres.wholphin.services.SetupNavigationManager import com.github.damontecres.wholphin.ui.FontAwesome @@ -98,11 +96,9 @@ class NavDrawerViewModel constructor( private val api: ApiClient, private val navDrawerService: NavDrawerService, - private val navDrawerItemRepository: NavDrawerItemRepository, val navigationManager: NavigationManager, val setupNavigationManager: SetupNavigationManager, val backdropService: BackdropService, - private val seerrServerRepository: SeerrServerRepository, ) : ViewModel() { val state = navDrawerService.state @@ -184,9 +180,13 @@ data class ServerNavDrawerItem( val destination: Destination, val type: CollectionType, ) : NavDrawerItem { - override val id: String = "s_" + itemId.toServerString() + override val id: String = getId(itemId) override fun name(context: Context): String = name + + companion object { + fun getId(itemId: UUID) = "s_" + itemId.toServerString() + } } /** diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/PreferencesViewModel.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/PreferencesViewModel.kt index 4113dbea2..97223b890 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/PreferencesViewModel.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/PreferencesViewModel.kt @@ -5,7 +5,6 @@ import androidx.datastore.core.DataStore import androidx.lifecycle.ViewModel import androidx.lifecycle.asFlow import androidx.lifecycle.viewModelScope -import com.github.damontecres.wholphin.data.NavDrawerItemRepository import com.github.damontecres.wholphin.data.ServerPreferencesDao import com.github.damontecres.wholphin.data.ServerRepository import com.github.damontecres.wholphin.data.model.JellyfinUser @@ -50,7 +49,6 @@ class PreferencesViewModel val backdropService: BackdropService, private val rememberTabManager: RememberTabManager, private val serverRepository: ServerRepository, - private val navDrawerItemRepository: NavDrawerItemRepository, private val navDrawerService: NavDrawerService, private val serverPreferencesDao: ServerPreferencesDao, private val seerrServerRepository: SeerrServerRepository, @@ -58,9 +56,6 @@ class PreferencesViewModel private val clientInfo: ClientInfo, ) : ViewModel(), RememberTabManager by rememberTabManager { - private lateinit var allNavDrawerItems: List -// val navDrawerPins = MutableLiveData>(emptyList()) - val navDrawerPins = navDrawerService.state .combine( From 8a79f62942e815356244a9b5efbbf7486b263501 Mon Sep 17 00:00:00 2001 From: Damontecres Date: Thu, 12 Feb 2026 20:59:42 -0500 Subject: [PATCH 2/2] Fix tests --- .../com/github/damontecres/wholphin/test/TestHomeRowSamples.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/test/java/com/github/damontecres/wholphin/test/TestHomeRowSamples.kt b/app/src/test/java/com/github/damontecres/wholphin/test/TestHomeRowSamples.kt index 3aedb3ba9..675b8b26f 100644 --- a/app/src/test/java/com/github/damontecres/wholphin/test/TestHomeRowSamples.kt +++ b/app/src/test/java/com/github/damontecres/wholphin/test/TestHomeRowSamples.kt @@ -121,8 +121,9 @@ class TestHomeRowSamples { HomeSettingsService( context = mockk(), api = mockk(), + serverRepository = mockk(), userPreferencesService = mockk(), - navDrawerItemRepository = mockk(), + navDrawerService = mockk(), latestNextUpService = mockk(), imageUrlService = mockk(), suggestionService = mockk(),