Fixes to default home view options for music & videos (#1926)

## Description
This PR fixes how cards are displayed initially when creating the
default home page or loading it from the web config:
- Ensure view options are selected based on the library type (this is
how it's done already when manually adding a row)
- Support more home row types such as photos and music

### Related issues
Fixes https://github.com/damontecres/Wholphin/issues/1838

### Testing
Emulator, resetting to default and loading from web config

## Screenshots
N/A, music cards will be square instead of poster sized

## AI or LLM usage
None
This commit is contained in:
Damontecres 2026-09-01 17:52:47 -04:00 • committed by GitHub
parent cedca9b2b1
commit 6fbf6209a1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 68 additions and 43 deletions

View file

@ -7,11 +7,14 @@ import com.github.damontecres.wholphin.data.ServerRepository
import com.github.damontecres.wholphin.data.model.BaseItem import com.github.damontecres.wholphin.data.model.BaseItem
import com.github.damontecres.wholphin.data.model.HomePageSettings import com.github.damontecres.wholphin.data.model.HomePageSettings
import com.github.damontecres.wholphin.data.model.HomeRowConfig import com.github.damontecres.wholphin.data.model.HomeRowConfig
import com.github.damontecres.wholphin.data.model.HomeRowViewOptions
import com.github.damontecres.wholphin.data.model.SUPPORTED_HOME_PAGE_SETTINGS_VERSION import com.github.damontecres.wholphin.data.model.SUPPORTED_HOME_PAGE_SETTINGS_VERSION
import com.github.damontecres.wholphin.data.model.createGenreDestination import com.github.damontecres.wholphin.data.model.createGenreDestination
import com.github.damontecres.wholphin.data.model.createStudioDestination import com.github.damontecres.wholphin.data.model.createStudioDestination
import com.github.damontecres.wholphin.preferences.DefaultUserConfiguration import com.github.damontecres.wholphin.preferences.DefaultUserConfiguration
import com.github.damontecres.wholphin.preferences.HomePagePreferences import com.github.damontecres.wholphin.preferences.HomePagePreferences
import com.github.damontecres.wholphin.ui.AspectRatio
import com.github.damontecres.wholphin.ui.Cards
import com.github.damontecres.wholphin.ui.HomeItemFields import com.github.damontecres.wholphin.ui.HomeItemFields
import com.github.damontecres.wholphin.ui.ProgramItemFields import com.github.damontecres.wholphin.ui.ProgramItemFields
import com.github.damontecres.wholphin.ui.components.getGenreImageMap import com.github.damontecres.wholphin.ui.components.getGenreImageMap
@ -36,7 +39,6 @@ import com.github.damontecres.wholphin.util.GetRecordingsRequestHandler
import com.github.damontecres.wholphin.util.GetStudiosRequestHandler import com.github.damontecres.wholphin.util.GetStudiosRequestHandler
import com.github.damontecres.wholphin.util.HomeRowLoadingState import com.github.damontecres.wholphin.util.HomeRowLoadingState
import com.github.damontecres.wholphin.util.HomeRowLoadingState.Success import com.github.damontecres.wholphin.util.HomeRowLoadingState.Success
import com.github.damontecres.wholphin.util.supportedHomeCollectionTypes
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -55,7 +57,6 @@ import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.extensions.liveTvApi import org.jellyfin.sdk.api.client.extensions.liveTvApi
import org.jellyfin.sdk.api.client.extensions.userApi import org.jellyfin.sdk.api.client.extensions.userApi
import org.jellyfin.sdk.api.client.extensions.userLibraryApi import org.jellyfin.sdk.api.client.extensions.userLibraryApi
import org.jellyfin.sdk.api.client.extensions.userViewsApi
import org.jellyfin.sdk.model.DateTime import org.jellyfin.sdk.model.DateTime
import org.jellyfin.sdk.model.UUID import org.jellyfin.sdk.model.UUID
import org.jellyfin.sdk.model.api.BaseItemKind import org.jellyfin.sdk.model.api.BaseItemKind
@ -280,20 +281,25 @@ class HomeSettingsService
val includedIds = val includedIds =
libraries libraries
.mapIndexed { index, it -> .mapIndexed { index, library ->
val parentId = it.itemId val parentId = library.itemId
val title = getRecentlyAddedTitle(it.name) val title = getRecentlyAddedTitle(library.name)
if (it.collectionType == CollectionType.LIVETV) { if (library.collectionType == CollectionType.LIVETV) {
HomeRowConfigDisplay( HomeRowConfigDisplay(
id = index, id = index,
title = ResStringProvider(R.string.watch_live), title = ResStringProvider(R.string.watch_live),
config = HomeRowConfig.TvPrograms(), config = HomeRowConfig.TvPrograms(),
) )
} else { } else {
val viewOptions = viewOptionsForCollectionType(library.collectionType)
HomeRowConfigDisplay( HomeRowConfigDisplay(
id = index, id = index,
title = title, title = title,
config = HomeRowConfig.RecentlyAdded(parentId), config =
HomeRowConfig.RecentlyAdded(
parentId = parentId,
viewOptions = viewOptions,
),
) )
} }
} }
@ -323,12 +329,10 @@ class HomeSettingsService
val userDto by api.userApi.getUserById(userId) val userDto by api.userApi.getUserById(userId)
val config = userDto.configuration ?: DefaultUserConfiguration val config = userDto.configuration ?: DefaultUserConfiguration
val libraries = val libraries =
api.userViewsApi navDrawerService
.getUserViews(userId = userId) .getAllUserLibraries(userId, userDto.tvAccess)
.content.items .filterNot {
.filter { it.itemId in config.latestItemsExcludes
it.collectionType in supportedHomeCollectionTypes &&
it.id !in config.latestItemsExcludes
} }
return if (customPrefs.isNotEmpty()) { return if (customPrefs.isNotEmpty()) {
@ -401,15 +405,21 @@ class HomeSettingsService
} }
} }
if (sectionType == HomeSectionType.LATEST_MEDIA) { if (sectionType == HomeSectionType.LATEST_MEDIA) {
libraries.map { libraries.map { library ->
val viewOptions =
viewOptionsForCollectionType(library.collectionType)
HomeRowConfigDisplay( HomeRowConfigDisplay(
id = id++, id = id++,
title = title =
ResArgStringProvider( ResArgStringProvider(
R.string.recently_added_in, R.string.recently_added_in,
it.name ?: "", library.name ?: "",
),
config =
HomeRowConfig.RecentlyAdded(
parentId = library.itemId,
viewOptions = viewOptions,
), ),
config = HomeRowConfig.RecentlyAdded(it.id),
) )
} }
} else if (config != null) { } else if (config != null) {
@ -1261,3 +1271,42 @@ private val Library?.itemFields: List<ItemFields>
} }
private val HomeItemFieldsBoxSets get() = HomeItemFields + listOf(ItemFields.CHILD_COUNT) private val HomeItemFieldsBoxSets get() = HomeItemFields + listOf(ItemFields.CHILD_COUNT)
fun viewOptionsForCollectionType(collectionType: CollectionType?): HomeRowViewOptions =
when (collectionType) {
CollectionType.MUSIC,
-> {
HomeRowViewOptions(
heightDp = Cards.HEIGHT_EPISODE,
aspectRatio = AspectRatio.SQUARE,
)
}
CollectionType.PHOTOS,
CollectionType.HOMEVIDEOS,
CollectionType.MUSICVIDEOS,
CollectionType.TRAILERS,
-> {
HomeRowViewOptions(
heightDp = Cards.HEIGHT_EPISODE,
aspectRatio = AspectRatio.WIDE,
)
}
CollectionType.LIVETV,
-> {
HomeRowViewOptions.liveTvDefault
}
CollectionType.MOVIES,
CollectionType.TVSHOWS,
CollectionType.BOXSETS,
CollectionType.BOOKS,
CollectionType.PLAYLISTS,
CollectionType.FOLDERS,
CollectionType.UNKNOWN,
null,
-> {
HomeRowViewOptions()
}
}

View file

@ -34,7 +34,7 @@ import com.github.damontecres.wholphin.services.UserPreferencesService
import com.github.damontecres.wholphin.services.getRecentlyAddedTitle import com.github.damontecres.wholphin.services.getRecentlyAddedTitle
import com.github.damontecres.wholphin.services.hilt.IoCoroutineScope import com.github.damontecres.wholphin.services.hilt.IoCoroutineScope
import com.github.damontecres.wholphin.services.tvAccess import com.github.damontecres.wholphin.services.tvAccess
import com.github.damontecres.wholphin.ui.AspectRatio import com.github.damontecres.wholphin.services.viewOptionsForCollectionType
import com.github.damontecres.wholphin.ui.formatTypeName import com.github.damontecres.wholphin.ui.formatTypeName
import com.github.damontecres.wholphin.ui.launchDefault import com.github.damontecres.wholphin.ui.launchDefault
import com.github.damontecres.wholphin.ui.launchIO import com.github.damontecres.wholphin.ui.launchIO
@ -275,24 +275,7 @@ class HomeSettingsViewModel
rowType: LibraryRowType, rowType: LibraryRowType,
): Job = ): Job =
viewModelScope.launchIO { viewModelScope.launchIO {
val viewOptions = val viewOptions = viewOptionsForCollectionType(library.collectionType)
when (library.collectionType) {
CollectionType.MUSIC -> {
HomeRowViewOptions(aspectRatio = AspectRatio.SQUARE)
}
CollectionType.HOMEVIDEOS,
CollectionType.MUSICVIDEOS,
-> {
HomeRowViewOptions(
aspectRatio = AspectRatio.WIDE,
)
}
else -> {
HomeRowViewOptions()
}
}
val id = idCounter++ val id = idCounter++
val newRow = val newRow =
when (rowType) { when (rowType) {

View file

@ -33,14 +33,7 @@ val supportedCollectionTypes =
CollectionType.MUSICVIDEOS, CollectionType.MUSICVIDEOS,
CollectionType.FOLDERS, CollectionType.FOLDERS,
CollectionType.MUSIC, CollectionType.MUSIC,
null, // Mixed CollectionType.PHOTOS,
)
val supportedHomeCollectionTypes =
setOf(
CollectionType.MOVIES,
CollectionType.TVSHOWS,
CollectionType.HOMEVIDEOS,
null, // Mixed null, // Mixed
) )