Separate type for continue & next up

This commit is contained in:
Damontecres 2026-01-23 19:39:57 -05:00
parent 00f6de8ec4
commit a90e6bc7b0
No known key found for this signature in database
4 changed files with 159 additions and 48 deletions

View file

@ -27,7 +27,22 @@ sealed class HomeRowConfig {
@Serializable
data class ContinueWatching(
override val id: UUID,
val combined: Boolean,
override val viewOptions: HomeRowViewOptions,
) : HomeRowConfig() {
override fun updateViewOptions(viewOptions: HomeRowViewOptions): HomeRowConfig = this.copy(viewOptions = viewOptions)
}
@Serializable
data class NextUp(
override val id: UUID,
override val viewOptions: HomeRowViewOptions,
) : HomeRowConfig() {
override fun updateViewOptions(viewOptions: HomeRowViewOptions): HomeRowConfig = this.copy(viewOptions = viewOptions)
}
@Serializable
data class ContinueWatchingCombined(
override val id: UUID,
override val viewOptions: HomeRowViewOptions,
) : HomeRowConfig() {
override fun updateViewOptions(viewOptions: HomeRowViewOptions): HomeRowConfig = this.copy(viewOptions = viewOptions)

View file

@ -1,11 +1,13 @@
package com.github.damontecres.wholphin.ui.main.settings
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material3.HorizontalDivider
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
@ -13,9 +15,11 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.focusRestorer
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.tv.material3.ListItem
import androidx.tv.material3.Text
import com.github.damontecres.wholphin.R
import com.github.damontecres.wholphin.ui.ifElse
import com.github.damontecres.wholphin.ui.tryRequestFocus
@ -23,6 +27,7 @@ import com.github.damontecres.wholphin.ui.tryRequestFocus
fun HomePageLibraryList(
libraries: List<Library>,
onClick: (Library) -> Unit,
onClickMeta: (MetaRowType) -> Unit,
modifier: Modifier,
firstFocus: FocusRequester = remember { FocusRequester() },
) {
@ -39,6 +44,19 @@ fun HomePageLibraryList(
.fillMaxHeight()
.focusRestorer(firstFocus),
) {
itemsIndexed(MetaRowType.entries) { index, type ->
ListItem(
selected = false,
headlineContent = {
Text(stringResource(type.stringId))
},
onClick = { onClickMeta.invoke(type) },
modifier = Modifier.ifElse(index == 0, Modifier.focusRequester(firstFocus)),
)
}
item {
HorizontalDivider()
}
itemsIndexed(libraries) { index, library ->
ListItem(
selected = false,
@ -46,9 +64,17 @@ fun HomePageLibraryList(
Text(library.name)
},
onClick = { onClick.invoke(library) },
modifier = Modifier.ifElse(index == 0, Modifier.focusRequester(firstFocus)),
modifier = Modifier, // .ifElse(index == 0, Modifier.focusRequester(firstFocus)),
)
}
}
}
}
enum class MetaRowType(
@param:StringRes val stringId: Int,
) {
CONTINUE_WATCHING(R.string.continue_watching),
NEXT_UP(R.string.next_up),
COMBINED_CONTINUE_WATCHING(R.string.combine_continue_next),
}

View file

@ -30,7 +30,6 @@ import androidx.tv.material3.MaterialTheme
import androidx.tv.material3.Text
import androidx.tv.material3.surfaceColorAtElevation
import com.github.damontecres.wholphin.R
import com.github.damontecres.wholphin.data.model.HomeRowConfig
import com.github.damontecres.wholphin.data.model.HomeRowConfigDisplay
import com.github.damontecres.wholphin.ui.FontAwesome
import com.github.damontecres.wholphin.ui.components.Button
@ -64,7 +63,7 @@ fun HomePageRowList(
config = row,
moveUpAllowed = index > 0,
moveDownAllowed = index != state.rows.lastIndex,
deleteAllowed = row.config !is HomeRowConfig.ContinueWatching,
deleteAllowed = true,
onClickMove = { onClickMove.invoke(it, index) },
onClickDelete = { onClickDelete.invoke(index) },
onClick = { onClick.invoke(index, row) },

View file

@ -111,17 +111,36 @@ class HomePageSettingsViewModel
),
)
}
val rowConfig =
listOf(
HomeRowConfigDisplay(
context.getString(R.string.continue_watching),
HomeRowConfig.ContinueWatching(
UUID.randomUUID(),
prefs.combineContinueNext,
HomeRowViewOptions(),
val continueWatchingRows =
if (prefs.combineContinueNext) {
listOf(
HomeRowConfigDisplay(
context.getString(R.string.combine_continue_next),
HomeRowConfig.ContinueWatchingCombined(
UUID.randomUUID(),
HomeRowViewOptions(),
),
),
),
) + includedIds
)
} else {
listOf(
HomeRowConfigDisplay(
context.getString(R.string.continue_watching),
HomeRowConfig.ContinueWatching(
UUID.randomUUID(),
HomeRowViewOptions(),
),
),
HomeRowConfigDisplay(
context.getString(R.string.next_up),
HomeRowConfig.NextUp(
UUID.randomUUID(),
HomeRowViewOptions(),
),
),
)
}
val rowConfig = continueWatchingRows + includedIds
_state.update {
it.copy(rows = rowConfig)
}
@ -148,6 +167,16 @@ class HomePageSettingsViewModel
when (row) {
is HomeRowConfig.ContinueWatching -> {
val resume = latestNextUpService.getResume(userDto.id, limit, true)
listOf(
HomeRowLoadingState.Success(
title = context.getString(R.string.continue_watching),
items = resume,
viewOptions = row.viewOptions,
),
)
}
is HomeRowConfig.NextUp -> {
val nextUp =
latestNextUpService.getNextUp(
userDto.id,
@ -155,40 +184,37 @@ class HomePageSettingsViewModel
prefs.enableRewatchingNextUp,
false,
)
val watching =
buildList {
if (row.combined) {
val items =
latestNextUpService.buildCombined(resume, nextUp)
add(
HomeRowLoadingState.Success(
title = context.getString(R.string.continue_watching),
items = items,
viewOptions = row.viewOptions,
),
)
} else {
if (resume.isNotEmpty()) {
add(
HomeRowLoadingState.Success(
title = context.getString(R.string.continue_watching),
items = resume,
viewOptions = row.viewOptions,
),
)
}
if (nextUp.isNotEmpty()) {
add(
HomeRowLoadingState.Success(
title = context.getString(R.string.next_up),
items = nextUp,
viewOptions = row.viewOptions,
),
)
}
}
}
watching
listOf(
HomeRowLoadingState.Success(
title = context.getString(R.string.next_up),
items = nextUp,
viewOptions = row.viewOptions,
),
)
}
is HomeRowConfig.ContinueWatchingCombined -> {
val resume =
latestNextUpService.getResume(userDto.id, limit, true)
val nextUp =
latestNextUpService.getNextUp(
userDto.id,
limit,
prefs.enableRewatchingNextUp,
false,
)
listOf(
HomeRowLoadingState.Success(
title = context.getString(R.string.continue_watching),
items =
latestNextUpService.buildCombined(
resume,
nextUp,
),
viewOptions = row.viewOptions,
),
)
}
is HomeRowConfig.Genres -> {
@ -321,6 +347,50 @@ class HomePageSettingsViewModel
}
}
fun addRow(type: MetaRowType) {
viewModelScope.launchIO {
val newRow =
when (type) {
MetaRowType.CONTINUE_WATCHING -> {
HomeRowConfigDisplay(
context.getString(R.string.continue_watching),
HomeRowConfig.ContinueWatching(
UUID.randomUUID(),
HomeRowViewOptions(),
),
)
}
MetaRowType.NEXT_UP -> {
HomeRowConfigDisplay(
context.getString(R.string.continue_watching),
HomeRowConfig.NextUp(
UUID.randomUUID(),
HomeRowViewOptions(),
),
)
}
MetaRowType.COMBINED_CONTINUE_WATCHING -> {
HomeRowConfigDisplay(
context.getString(R.string.combine_continue_next),
HomeRowConfig.ContinueWatchingCombined(
UUID.randomUUID(),
HomeRowViewOptions(),
),
)
}
}
_state.update {
it.copy(
loading = LoadingState.Loading,
rows = it.rows.toMutableList().apply { add(newRow) },
)
}
fetchRowData()
}
}
fun addRow(
library: Library,
rowType: LibraryRowType,
@ -510,6 +580,7 @@ fun HomePageSettings(
HomePageLibraryList(
libraries = state.libraries,
onClick = { destination = HomePageSettingsDestination.ChooseRowType(it) },
onClickMeta = { viewModel.addRow(it) },
modifier = destModifier,
)
}