From 91900af7a925f8bfe08173d1f1cb6c955530d833 Mon Sep 17 00:00:00 2001
From: Ray <154766448+damontecres@users.noreply.github.com>
Date: Fri, 13 Feb 2026 11:41:47 -0500
Subject: [PATCH] Improved home page support for Live TV & Recordings (#890)
## Description
Improves home page customization for Live TV & Recordings
- Add row for live tv channels
- Add row for "on now" programs
- Clicking on a TV channel or TV program starts playback
- Better name for "Recently recorded" instead of "Recently added in
Recordings"
Also fixes a back stack issue after adding rows
### Related issues
Follow up from #803
### Testing
Emulator
## Screenshots
## AI or LLM usage
None
---
.../wholphin/data/model/BaseItem.kt | 19 +++++
.../wholphin/data/model/HomeRowConfig.kt | 21 ++++-
.../wholphin/preferences/AppPreference.kt | 1 +
.../wholphin/services/HomeSettingsService.kt | 81 ++++++++++++++-----
.../wholphin/services/NavDrawerService.kt | 74 ++++++++++-------
.../damontecres/wholphin/ui/UiConstants.kt | 2 +-
.../wholphin/ui/main/HomeViewModel.kt | 4 +-
.../main/settings/HomeLibraryRowTypeList.kt | 41 ++++++++--
.../ui/main/settings/HomeSettingsPage.kt | 4 +-
.../ui/main/settings/HomeSettingsViewModel.kt | 41 +++++++++-
.../wholphin/ui/nav/DestinationContent.kt | 2 +-
app/src/main/res/values/strings.xml | 1 +
.../wholphin/test/TestHomeRowSamples.kt | 2 +
13 files changed, 229 insertions(+), 64 deletions(-)
diff --git a/app/src/main/java/com/github/damontecres/wholphin/data/model/BaseItem.kt b/app/src/main/java/com/github/damontecres/wholphin/data/model/BaseItem.kt
index 3030b7d0..172c6ef5 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/data/model/BaseItem.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/data/model/BaseItem.kt
@@ -187,6 +187,25 @@ data class BaseItem(
)
}
+ BaseItemKind.TV_CHANNEL -> {
+ Destination.Playback(
+ itemId = id,
+ positionMs = 0L,
+ )
+ }
+
+ BaseItemKind.PROGRAM -> {
+ val channelId = data.channelId
+ if (channelId != null) {
+ Destination.Playback(
+ itemId = channelId,
+ positionMs = 0L,
+ )
+ } else {
+ Destination.MediaItem(this)
+ }
+ }
+
else -> {
Destination.MediaItem(this)
}
diff --git a/app/src/main/java/com/github/damontecres/wholphin/data/model/HomeRowConfig.kt b/app/src/main/java/com/github/damontecres/wholphin/data/model/HomeRowConfig.kt
index 7d521ce4..c11ad321 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/data/model/HomeRowConfig.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/data/model/HomeRowConfig.kt
@@ -111,7 +111,7 @@ sealed interface HomeRowConfig {
}
/**
- *
+ * Currently recording
*/
@Serializable
@SerialName("Recordings")
@@ -122,7 +122,7 @@ sealed interface HomeRowConfig {
}
/**
- *
+ * Programs on now/recommended
*/
@Serializable
@SerialName("TvPrograms")
@@ -132,6 +132,17 @@ sealed interface HomeRowConfig {
override fun updateViewOptions(viewOptions: HomeRowViewOptions): TvPrograms = this.copy(viewOptions = viewOptions)
}
+ /**
+ * Live TV channels
+ */
+ @Serializable
+ @SerialName("TvChannels")
+ data class TvChannels(
+ override val viewOptions: HomeRowViewOptions = HomeRowViewOptions(),
+ ) : HomeRowConfig {
+ override fun updateViewOptions(viewOptions: HomeRowViewOptions): TvChannels = this.copy(viewOptions = viewOptions)
+ }
+
/**
* Fetch suggestions from [com.github.damontecres.wholphin.services.SuggestionService] for the given parent ID
*/
@@ -217,5 +228,11 @@ data class HomeRowViewOptions(
heightDp = Cards.HEIGHT_EPISODE,
aspectRatio = AspectRatio.WIDE,
)
+
+ val channelsDefault =
+ HomeRowViewOptions(
+ heightDp = 96,
+ aspectRatio = AspectRatio.WIDE,
+ )
}
}
diff --git a/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreference.kt b/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreference.kt
index 7eaa2ffe..709abd6c 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreference.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreference.kt
@@ -660,6 +660,7 @@ sealed interface AppPreference {
AppDestinationPreference(
title = R.string.customize_home,
destination = Destination.HomeSettings,
+ summary = R.string.customize_home_summary,
)
val SendCrashReports =
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 083d461d..99ced240 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
@@ -12,13 +12,14 @@ 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.toBaseItems
import com.github.damontecres.wholphin.ui.toServerString
import com.github.damontecres.wholphin.util.GetGenresRequestHandler
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
import com.github.damontecres.wholphin.util.GetPersonsHandler
import com.github.damontecres.wholphin.util.HomeRowLoadingState
+import com.github.damontecres.wholphin.util.HomeRowLoadingState.Error
import com.github.damontecres.wholphin.util.HomeRowLoadingState.Success
import com.github.damontecres.wholphin.util.supportedHomeCollectionTypes
import dagger.hilt.android.qualifiers.ApplicationContext
@@ -43,6 +44,7 @@ import org.jellyfin.sdk.api.client.extensions.userLibraryApi
import org.jellyfin.sdk.api.client.extensions.userViewsApi
import org.jellyfin.sdk.model.UUID
import org.jellyfin.sdk.model.api.BaseItemKind
+import org.jellyfin.sdk.model.api.CollectionType
import org.jellyfin.sdk.model.api.ImageType
import org.jellyfin.sdk.model.api.ItemSortBy
import org.jellyfin.sdk.model.api.SortOrder
@@ -255,11 +257,12 @@ class HomeSettingsService
suspend fun createDefault(userId: UUID): HomePageResolvedSettings {
Timber.v("Creating default settings")
val user = serverRepository.currentUser.value?.takeIf { it.id == userId }
+ val userDto = serverRepository.currentUserDto.value?.takeIf { it.id == userId }
val libraries =
if (user != null) {
- navDrawerService.getFilteredUserLibraries(user)
+ navDrawerService.getFilteredUserLibraries(user, userDto?.tvAccess ?: false)
} else {
- navDrawerService.getAllUserLibraries(userId)
+ navDrawerService.getAllUserLibraries(userId, userDto?.tvAccess ?: false)
}
val prefs =
@@ -269,18 +272,23 @@ class HomeSettingsService
libraries
.mapIndexed { index, it ->
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)
- HomeRowConfigDisplay(
- id = index,
- title = title,
- config = HomeRowConfig.RecentlyAdded(parentId),
- )
+ val title = getRecentlyAddedTitle(context, it)
+ if (it.collectionType == CollectionType.LIVETV) {
+ HomeRowConfigDisplay(
+ id = index,
+ title = context.getString(R.string.live_tv),
+ config = HomeRowConfig.TvPrograms(),
+ )
+ } else {
+ HomeRowConfigDisplay(
+ id = index,
+ title = title,
+ config = HomeRowConfig.RecentlyAdded(parentId),
+ )
+ }
}
val continueWatchingRows =
- if (prefs.combineContinueNext) { // TODO
+ if (prefs.combineContinueNext) {
listOf(
HomeRowConfigDisplay(
id = includedIds.size + 1,
@@ -363,7 +371,7 @@ class HomeSettingsService
}
HomeSectionType.LIVE_TV -> {
- if (userDto.policy?.enableLiveTvAccess == true) {
+ if (userDto.tvAccess) {
HomeRowConfigDisplay(
id = id++,
title = context.getString(R.string.live_tv),
@@ -523,6 +531,14 @@ class HomeSettingsService
)
}
+ is HomeRowConfig.TvChannels -> {
+ HomeRowConfigDisplay(
+ id = id,
+ title = context.getString(R.string.channels),
+ config,
+ )
+ }
+
is HomeRowConfig.Suggestions -> {
val name =
api.userLibraryApi
@@ -654,13 +670,10 @@ class HomeSettingsService
}
is HomeRowConfig.RecentlyAdded -> {
- val name =
+ val library =
libraries
.firstOrNull { it.itemId == row.parentId }
- ?.name
- val title =
- name?.let { context.getString(R.string.recently_added_in, it) }
- ?: context.getString(R.string.recently_added)
+ val title = getRecentlyAddedTitle(context, library)
val request =
GetLatestMediaRequest(
fields = SlimItemFields,
@@ -862,6 +875,23 @@ class HomeSettingsService
}
}
+ is HomeRowConfig.TvChannels -> {
+ api.liveTvApi
+ .getLiveTvChannels(
+ userId = userDto.id,
+ fields = DefaultItemFields,
+ limit = limit,
+ enableImages = true,
+ ).toBaseItems(api, row.viewOptions.useSeries)
+ .let {
+ Success(
+ context.getString(R.string.channels),
+ it,
+ row.viewOptions,
+ )
+ }
+ }
+
is HomeRowConfig.Suggestions -> {
val library =
api.userLibraryApi
@@ -888,7 +918,7 @@ class HomeSettingsService
row.viewOptions,
)
} else {
- HomeRowLoadingState.Error(
+ Error(
title,
message = "Unsupported type ${library.collectionType}",
)
@@ -949,3 +979,14 @@ class UnsupportedHomeSettingsVersionException(
val unsupportedVersion: Int?,
val maxSupportedVersion: Int = SUPPORTED_HOME_PAGE_SETTINGS_VERSION,
) : Exception("Unsupported version $unsupportedVersion, max supported is $maxSupportedVersion")
+
+fun getRecentlyAddedTitle(
+ context: Context,
+ library: Library?,
+): String =
+ if (library?.isRecordingFolder == true) {
+ context.getString(R.string.recently_recorded)
+ } else {
+ library?.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 fbce042c..adb21ff7 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
@@ -4,7 +4,6 @@ import android.content.Context
import androidx.lifecycle.asFlow
import com.github.damontecres.wholphin.data.ServerPreferencesDao
import com.github.damontecres.wholphin.data.ServerRepository
-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
@@ -68,25 +67,49 @@ class NavDrawerService
}.launchIn(coroutineScope)
}
- suspend fun getAllUserLibraries(userId: UUID): List {
+ suspend fun getAllUserLibraries(
+ userId: UUID,
+ tvAccess: Boolean,
+ ): List {
val userViews =
api.userViewsApi
.getUserViews(userId = userId)
.content.items
+ val recordingFolders =
+ if (tvAccess) {
+ api.liveTvApi
+ .getRecordingFolders(userId = userId)
+ .content.items
+ .map { it.id }
+ .toSet()
+ } else {
+ setOf()
+ }
val libraries =
userViews
- .filter { it.collectionType in supportedCollectionTypes }
- .map { Library(it.id, it.name ?: "", it.collectionType ?: CollectionType.UNKNOWN) }
+ .filter { it.collectionType in supportedCollectionTypes || it.id in recordingFolders }
+ .map {
+ Library(
+ itemId = it.id,
+ name = it.name ?: "",
+ type = it.type,
+ collectionType = it.collectionType ?: CollectionType.UNKNOWN,
+ isRecordingFolder = it.id in recordingFolders,
+ )
+ }
return libraries
}
- suspend fun getFilteredUserLibraries(user: JellyfinUser): List {
+ suspend fun getFilteredUserLibraries(
+ user: JellyfinUser,
+ tvAccess: Boolean,
+ ): List {
val pins =
serverPreferencesDao
.getNavDrawerPinnedItems(user)
.associateBy { it.itemId }
val libraries =
- getAllUserLibraries(user.id)
+ getAllUserLibraries(user.id, tvAccess)
.filterNot { pins[ServerNavDrawerItem.getId(it.itemId)]?.type == NavPinType.UNPINNED }
return libraries
}
@@ -95,39 +118,26 @@ class NavDrawerService
user: JellyfinUser,
userDto: UserDto,
) {
- val tvAccess = userDto.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 = listOf(NavDrawerItem.Favorites, NavDrawerItem.Discover)
-
+ val allLibraries = getAllUserLibraries(user.id, userDto.tvAccess)
val libraries =
- userViews
- .filter { it.collectionType in supportedCollectionTypes || it.id in recordingFolders }
+ allLibraries
.map {
val destination =
- if (it.id in recordingFolders) {
- Destination.Recordings(it.id)
+ if (it.isRecordingFolder) {
+ Destination.Recordings(it.itemId)
} else {
- BaseItem.from(it, api).destination()
+ Destination.MediaItem(
+ it.itemId,
+ it.type,
+ it.collectionType,
+ )
}
ServerNavDrawerItem(
- itemId = it.id,
- name = it.name ?: it.id.toString(),
+ itemId = it.itemId,
+ name = it.name,
destination = destination,
- type = it.collectionType ?: CollectionType.UNKNOWN,
+ type = it.collectionType,
)
}
val allItems = builtins + libraries
@@ -170,3 +180,5 @@ data class NavDrawerItemState(
val EMPTY = NavDrawerItemState(emptyList(), emptyList(), false)
}
}
+
+val UserDto.tvAccess: Boolean get() = policy?.enableLiveTvAccess == true
diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/UiConstants.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/UiConstants.kt
index 0db41202..2d9b6d5e 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/ui/UiConstants.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/ui/UiConstants.kt
@@ -84,7 +84,7 @@ val PhotoItemFields =
object Cards {
const val HEIGHT_2X3_DP = 172
val height2x3 = HEIGHT_2X3_DP.dp
- val HEIGHT_EPISODE = (HEIGHT_2X3_DP * .75f).toInt().let { it - it % 4 }
+ const val HEIGHT_EPISODE = 128
val heightEpisode = HEIGHT_EPISODE.dp
val playedPercentHeight = 6.dp
val serverUserCircle = height2x3 * .75f
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 1e72830f..58296848 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
@@ -15,6 +15,7 @@ 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.services.tvAccess
import com.github.damontecres.wholphin.ui.launchIO
import com.github.damontecres.wholphin.ui.showToast
import com.github.damontecres.wholphin.util.ExceptionHandler
@@ -68,7 +69,8 @@ class HomeViewModel
val prefs = preferences.appPreferences.homePagePreferences
serverRepository.currentUserDto.value?.let { userDto ->
- val libraries = navDrawerService.getAllUserLibraries(userDto.id)
+ val libraries =
+ navDrawerService.getAllUserLibraries(userDto.id, userDto.tvAccess)
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/HomeLibraryRowTypeList.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeLibraryRowTypeList.kt
index c680e077..87ce4d39 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeLibraryRowTypeList.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeLibraryRowTypeList.kt
@@ -23,6 +23,7 @@ import com.github.damontecres.wholphin.R
import com.github.damontecres.wholphin.services.SuggestionsWorker
import com.github.damontecres.wholphin.ui.ifElse
import com.github.damontecres.wholphin.ui.tryRequestFocus
+import org.jellyfin.sdk.model.api.CollectionType
@Composable
fun HomeLibraryRowTypeList(
@@ -63,11 +64,38 @@ fun HomeLibraryRowTypeList(
}
fun getSupportedRowTypes(library: Library): List {
- val itemKind = SuggestionsWorker.getTypeForCollection(library.collectionType)
- return if (itemKind != null) {
- LibraryRowType.entries
- } else {
- LibraryRowType.entries.toMutableList().apply { remove(LibraryRowType.SUGGESTIONS) }
+ val supportsSuggestions = SuggestionsWorker.getTypeForCollection(library.collectionType) != null
+ return when {
+ library.isRecordingFolder -> {
+ listOf(
+ LibraryRowType.RECENTLY_RECORDED,
+ LibraryRowType.GENRES,
+ )
+ }
+
+ library.collectionType == CollectionType.LIVETV -> {
+ listOf(
+ LibraryRowType.TV_CHANNELS,
+ LibraryRowType.TV_PROGRAMS,
+ )
+ }
+
+ supportsSuggestions -> {
+ listOf(
+ LibraryRowType.RECENTLY_ADDED,
+ LibraryRowType.RECENTLY_RELEASED,
+ LibraryRowType.SUGGESTIONS,
+ LibraryRowType.GENRES,
+ )
+ }
+
+ else -> {
+ listOf(
+ LibraryRowType.RECENTLY_ADDED,
+ LibraryRowType.RECENTLY_RELEASED,
+ LibraryRowType.GENRES,
+ )
+ }
}
}
@@ -78,4 +106,7 @@ enum class LibraryRowType(
RECENTLY_RELEASED(R.string.recently_released),
SUGGESTIONS(R.string.suggestions),
GENRES(R.string.genres),
+ TV_CHANNELS(R.string.channels),
+ TV_PROGRAMS(R.string.live_tv),
+ RECENTLY_RECORDED(R.string.recently_recorded),
}
diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeSettingsPage.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeSettingsPage.kt
index 616eff13..17a02b59 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeSettingsPage.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomeSettingsPage.kt
@@ -61,7 +61,9 @@ fun HomeSettingsPage(
// Adds a row, waits until its done loading, then scrolls to the new row
fun addRow(func: () -> Job) {
scope.launch(ExceptionHandler(autoToast = true)) {
- backStack.add(HomeSettingsDestination.RowList)
+ while (backStack.size > 1) {
+ backStack.removeAt(backStack.lastIndex)
+ }
func.invoke().join()
listState.animateScrollToItem(state.rows.lastIndex)
}
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 53c457ff..11fd058c 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
@@ -30,6 +30,7 @@ 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.services.tvAccess
import com.github.damontecres.wholphin.ui.launchIO
import com.github.damontecres.wholphin.ui.showToast
import com.github.damontecres.wholphin.util.HomeRowLoadingState
@@ -83,8 +84,8 @@ class HomeSettingsViewModel
init {
addCloseable { saveToLocal() }
viewModelScope.launchIO {
- val userId = serverRepository.currentUser.value?.id ?: return@launchIO
- val libraries = navDrawerService.getAllUserLibraries(userId)
+ val userDto = serverRepository.currentUserDto.value ?: return@launchIO
+ val libraries = navDrawerService.getAllUserLibraries(userDto.id, userDto.tvAccess)
val currentSettings =
homeSettingsService.currentSettings.first { it != HomePageResolvedSettings.EMPTY }
Timber.v("currentSettings=%s", currentSettings)
@@ -292,6 +293,36 @@ class HomeSettingsViewModel
config = Suggestions(library.itemId),
)
}
+
+ LibraryRowType.TV_CHANNELS -> {
+ val title = context.getString(R.string.channels)
+ HomeRowConfigDisplay(
+ id = id,
+ title = title,
+ config =
+ HomeRowConfig.TvChannels(
+ viewOptions = HomeRowViewOptions.channelsDefault,
+ ),
+ )
+ }
+
+ LibraryRowType.TV_PROGRAMS -> {
+ val title = context.getString(R.string.watch_live)
+ HomeRowConfigDisplay(
+ id = id,
+ title = title,
+ config = HomeRowConfig.TvPrograms(),
+ )
+ }
+
+ LibraryRowType.RECENTLY_RECORDED -> {
+ val title = context.getString(R.string.recently_recorded)
+ HomeRowConfigDisplay(
+ id = id,
+ title = title,
+ config = RecentlyAdded(library.itemId),
+ )
+ }
}
updateState {
it.copy(
@@ -614,6 +645,10 @@ class HomeSettingsViewModel
is HomeRowConfig.TvPrograms -> {
it.config.updateViewOptions(preset.tvLibrary)
}
+
+ is HomeRowConfig.TvChannels -> {
+ it.config
+ }
}
it.copy(config = newConfig)
}
@@ -658,5 +693,7 @@ data class HomePageSettingsState(
data class Library(
@Serializable(UUIDSerializer::class) val itemId: UUID,
val name: String,
+ val type: BaseItemKind,
val collectionType: CollectionType,
+ val isRecordingFolder: Boolean,
)
diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/nav/DestinationContent.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/nav/DestinationContent.kt
index a16e909a..eccfd6de 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/ui/nav/DestinationContent.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/ui/nav/DestinationContent.kt
@@ -214,7 +214,7 @@ fun DestinationContent(
else -> {
Timber.w("Unsupported item type: ${destination.type}")
- Text("Unsupported item type: ${destination.type}")
+ Text("Unsupported item type: ${destination.type}", modifier)
}
}
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index e8533441..3d7b1b5c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -520,6 +520,7 @@
Settings saved
Display presets
Built-in presets to quickly style all rows
+ Choose rows and images on the home page
- Disabled
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 675b8b26..84aa72b6 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
@@ -74,6 +74,7 @@ class TestHomeRowSamples {
HomeRowConfig.Favorite(kind = BaseItemKind.SERIES),
HomeRowConfig.Recordings(),
HomeRowConfig.TvPrograms(),
+ HomeRowConfig.TvChannels(),
HomeRowConfig.Suggestions(parentId = UUID.randomUUID()),
)
}
@@ -96,6 +97,7 @@ class TestHomeRowSamples {
is HomeRowConfig.Recordings -> foundTypes.add(it::class)
is HomeRowConfig.TvPrograms -> foundTypes.add(it::class)
is HomeRowConfig.Suggestions -> foundTypes.add(it::class)
+ is HomeRowConfig.TvChannels -> foundTypes.add(it::class)
}
}
Assert.assertEquals(HomeRowConfig::class.sealedSubclasses.size, foundTypes.size)