From 6d53869180c99133af935d029f990d25da4dd640 Mon Sep 17 00:00:00 2001 From: Damontecres Date: Fri, 23 Jan 2026 11:32:55 -0500 Subject: [PATCH] WIP, basic MVP --- .../damontecres/wholphin/MainActivity.kt | 3 +- .../wholphin/data/ServerRepository.kt | 22 ++ .../wholphin/data/model/HomeRowConfig.kt | 58 +++ .../damontecres/wholphin/ui/UiConstants.kt | 3 +- .../damontecres/wholphin/ui/main/HomePage.kt | 3 +- .../ui/main/settings/HomePageRowList.kt | 155 ++++++++ .../ui/main/settings/HomePageSettings.kt | 359 ++++++++++++++++++ .../settings/HomePageSettingsDestination.kt | 17 + .../wholphin/ui/nav/Destination.kt | 3 + .../wholphin/ui/nav/DestinationContent.kt | 5 + app/src/main/res/values/strings.xml | 2 + 11 files changed, 627 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/com/github/damontecres/wholphin/data/model/HomeRowConfig.kt create mode 100644 app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomePageRowList.kt create mode 100644 app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomePageSettings.kt create mode 100644 app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomePageSettingsDestination.kt diff --git a/app/src/main/java/com/github/damontecres/wholphin/MainActivity.kt b/app/src/main/java/com/github/damontecres/wholphin/MainActivity.kt index c7b12bfc..f127944e 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/MainActivity.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/MainActivity.kt @@ -265,7 +265,8 @@ class MainActivity : AppCompatActivity() { server = current.server, startDestination = requestedDestination - ?: Destination.Home(), + // TODO Undo + ?: Destination.HomeSettings, navigationManager = navigationManager, preferences = preferences, modifier = Modifier.fillMaxSize(), diff --git a/app/src/main/java/com/github/damontecres/wholphin/data/ServerRepository.kt b/app/src/main/java/com/github/damontecres/wholphin/data/ServerRepository.kt index f66dcfca..c0cd962d 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/data/ServerRepository.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/data/ServerRepository.kt @@ -18,6 +18,7 @@ import kotlinx.coroutines.withContext import kotlinx.serialization.Serializable import org.jellyfin.sdk.Jellyfin import org.jellyfin.sdk.api.client.ApiClient +import org.jellyfin.sdk.api.client.extensions.displayPreferencesApi import org.jellyfin.sdk.api.client.extensions.systemApi import org.jellyfin.sdk.api.client.extensions.userApi import org.jellyfin.sdk.model.api.AuthenticationResult @@ -102,6 +103,27 @@ class ServerRepository currentUserId = updatedUser.id.toServerString() }.build() } + val settings = + apiClient.displayPreferencesApi + .getDisplayPreferences( + displayPreferencesId = "settings", + userId = user.id, + client = "wholphin", + ).content + val newSettings = + settings.copy( + customPrefs = + settings.customPrefs.toMutableMap().apply { + put("test_key", "test_value") + }, + ) + apiClient.displayPreferencesApi.updateDisplayPreferences( + displayPreferencesId = "settings", + userId = user.id, + client = "wholphin", + data = newSettings, + ) + Timber.v("settings=$settings") withContext(Dispatchers.Main) { _current.value = CurrentUser(updatedServer, updatedUser) _currentUserDto.value = userDto 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 new file mode 100644 index 00000000..c88612cc --- /dev/null +++ b/app/src/main/java/com/github/damontecres/wholphin/data/model/HomeRowConfig.kt @@ -0,0 +1,58 @@ +@file:UseSerializers(UUIDSerializer::class) + +package com.github.damontecres.wholphin.data.model + +import com.github.damontecres.wholphin.preferences.PrefContentScale +import com.github.damontecres.wholphin.ui.AspectRatio +import com.github.damontecres.wholphin.ui.Cards +import com.github.damontecres.wholphin.ui.components.ViewOptionImageType +import kotlinx.serialization.Serializable +import kotlinx.serialization.UseSerializers +import org.jellyfin.sdk.model.serializer.UUIDSerializer +import java.util.UUID + +@Serializable +sealed class HomeRowConfig { + abstract val viewOptions: HomeRowViewOptions + + @Serializable + data class ContinueWatching( + val combined: Boolean, + override val viewOptions: HomeRowViewOptions, + ) : HomeRowConfig() + + @Serializable + data class RecentlyAdded( + val parentId: UUID, + override val viewOptions: HomeRowViewOptions, + ) : HomeRowConfig() + + @Serializable + data class RecentlyReleased( + val parentId: UUID, + override val viewOptions: HomeRowViewOptions, + ) : HomeRowConfig() + + @Serializable + data class Genres( + val genreId: UUID, + val parentId: UUID, + override val viewOptions: HomeRowViewOptions, + ) : HomeRowConfig() +} + +data class HomeRowConfigDisplay( + val title: String, + val config: HomeRowConfig, +) + +@Serializable +data class HomeRowViewOptions( + val heightDp: Int = Cards.HEIGHT_2X3_DP, + val spacing: Int = 16, + val contentScale: PrefContentScale = PrefContentScale.FIT, + val aspectRatio: AspectRatio = AspectRatio.TALL, + val imageType: ViewOptionImageType = ViewOptionImageType.PRIMARY, + val showTitles: Boolean = true, + val useSeries: Boolean = 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 54f564f1..0ea92dcd 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 @@ -73,7 +73,8 @@ val SlimItemFields = ) object Cards { - val height2x3 = 172.dp + const val HEIGHT_2X3_DP = 172 + val height2x3 = HEIGHT_2X3_DP.dp val heightEpisode = height2x3 * .75f val playedPercentHeight = 6.dp val serverUserCircle = height2x3 * .75f diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomePage.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomePage.kt index 33d40a4a..084c00d7 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomePage.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomePage.kt @@ -16,6 +16,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.runtime.Composable @@ -192,6 +193,7 @@ fun HomePageContent( modifier: Modifier = Modifier, onFocusPosition: ((RowColumn) -> Unit)? = null, loadingState: LoadingState? = null, + listState: LazyListState = rememberLazyListState(), ) { var position by rememberPosition() val focusedItem = @@ -199,7 +201,6 @@ fun HomePageContent( (homeRows.getOrNull(it.row) as? HomeRowLoadingState.Success)?.items?.getOrNull(it.column) } - val listState = rememberLazyListState() val rowFocusRequesters = remember(homeRows) { List(homeRows.size) { FocusRequester() } } var firstFocused by remember { mutableStateOf(false) } LaunchedEffect(homeRows) { diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomePageRowList.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomePageRowList.kt new file mode 100644 index 00000000..b011b480 --- /dev/null +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomePageRowList.kt @@ -0,0 +1,155 @@ +package com.github.damontecres.wholphin.ui.main.settings + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Delete +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +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.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.tv.material3.Icon +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.HomeRowConfigDisplay +import com.github.damontecres.wholphin.ui.FontAwesome +import com.github.damontecres.wholphin.ui.components.Button +import com.github.damontecres.wholphin.ui.ifElse + +enum class MoveDirection { + UP, + DOWN, +} + +@Composable +fun HomePageRowList( + state: HomePageSettingsState, + onClickAdd: () -> Unit, + onClickMove: (MoveDirection, Int) -> Unit, + onClickDelete: (Int) -> Unit, + modifier: Modifier, + firstFocus: FocusRequester = remember { FocusRequester() }, +) { + Column(modifier = modifier) { + LazyColumn( + contentPadding = PaddingValues(8.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + modifier = + modifier + .fillMaxHeight() + .focusRestorer(firstFocus), + ) { + itemsIndexed(state.rows) { index, row -> + HomeRowConfigContent( + config = row, + moveUpAllowed = index > 0, + moveDownAllowed = index != state.rows.lastIndex, + onClickMove = { onClickMove.invoke(it, index) }, + onClickDelete = { onClickDelete.invoke(index) }, + modifier = + Modifier + .fillMaxWidth() + .ifElse(index == 0, Modifier.focusRequester(firstFocus)), + ) + } + item { + Button( + onClick = onClickAdd, + modifier = Modifier.ifElse(state.rows.isEmpty(), Modifier.focusRequester(firstFocus)), + ) { + Text( + text = stringResource(R.string.add_row), + ) + } + } + } + } +} + +@Composable +fun HomeRowConfigContent( + config: HomeRowConfigDisplay, + moveUpAllowed: Boolean, + moveDownAllowed: Boolean, + onClickMove: (MoveDirection) -> Unit, + onClickDelete: () -> Unit, + modifier: Modifier, +) { + Box( + modifier = modifier, + ) { + Row( + horizontalArrangement = Arrangement.spacedBy(16.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = + Modifier + .fillMaxWidth() + .heightIn(min = 40.dp, max = 88.dp) + .background( + color = MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp), + shape = RoundedCornerShape(8.dp), + ).padding(8.dp), + ) { + Text( + text = config.title, + color = MaterialTheme.colorScheme.onSurface, + style = MaterialTheme.typography.titleMedium, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.weight(1f), + ) + Row( + horizontalArrangement = Arrangement.spacedBy(4.dp), + modifier = Modifier.wrapContentWidth(), + ) { + Button( + onClick = { onClickMove.invoke(MoveDirection.UP) }, + enabled = moveUpAllowed, + ) { + Text( + text = stringResource(R.string.fa_caret_up), + fontFamily = FontAwesome, + ) + } + Button( + onClick = { onClickMove.invoke(MoveDirection.DOWN) }, + enabled = moveDownAllowed, + ) { + Text( + text = stringResource(R.string.fa_caret_down), + fontFamily = FontAwesome, + ) + } + Button( + onClick = onClickDelete, + enabled = true, + ) { + Icon( + imageVector = Icons.Default.Delete, + contentDescription = "delete", + modifier = Modifier, + ) + } + } + } + } +} diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomePageSettings.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomePageSettings.kt new file mode 100644 index 00000000..79979638 --- /dev/null +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomePageSettings.kt @@ -0,0 +1,359 @@ +package com.github.damontecres.wholphin.ui.main.settings + +import android.content.Context +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import androidx.tv.material3.MaterialTheme +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.HomeRowConfig +import com.github.damontecres.wholphin.data.model.HomeRowConfigDisplay +import com.github.damontecres.wholphin.data.model.HomeRowViewOptions +import com.github.damontecres.wholphin.services.BackdropService +import com.github.damontecres.wholphin.services.LatestNextUpService +import com.github.damontecres.wholphin.services.UserPreferencesService +import com.github.damontecres.wholphin.ui.SlimItemFields +import com.github.damontecres.wholphin.ui.launchIO +import com.github.damontecres.wholphin.ui.main.HomePageContent +import com.github.damontecres.wholphin.ui.main.LatestData +import com.github.damontecres.wholphin.ui.nav.ServerNavDrawerItem +import com.github.damontecres.wholphin.util.GetGenresRequestHandler +import com.github.damontecres.wholphin.util.HomeRowLoadingState +import com.github.damontecres.wholphin.util.LoadingState +import dagger.hilt.android.lifecycle.HiltViewModel +import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update +import org.jellyfin.sdk.api.client.ApiClient +import org.jellyfin.sdk.model.api.CollectionType +import org.jellyfin.sdk.model.api.request.GetGenresRequest +import org.jellyfin.sdk.model.api.request.GetLatestMediaRequest +import java.util.UUID +import javax.inject.Inject + +@HiltViewModel +class HomePageSettingsViewModel + @Inject + 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 backdropService: BackdropService, + private val latestNextUpService: LatestNextUpService, + ) : ViewModel() { + private val _state = MutableStateFlow(HomePageSettingsState.EMPTY) + val state: StateFlow = _state + + init { + viewModelScope.launchIO { + val navDrawerItems = + navDrawerItemRepository + .getNavDrawerItems() + val libraries = + navDrawerItems + .filter { it is ServerNavDrawerItem } + .map { + it as ServerNavDrawerItem + Library(it.itemId, it.name, it.type) + } + _state.update { it.copy(libraries = libraries) } + + // TODO get config + + // Or create default + val prefs = userPreferencesService.getCurrent().appPreferences.homePagePreferences + val includedIds = + navDrawerItemRepository + .getFilteredNavDrawerItems(navDrawerItems) + .filter { it is ServerNavDrawerItem } + .map { + val id = (it as ServerNavDrawerItem).itemId + val name = libraries.firstOrNull { it.itemId == id }?.name + val title = + name?.let { context.getString(R.string.recently_added_in, it) } + ?: context.getString(R.string.recently_added) + HomeRowConfigDisplay( + title, + HomeRowConfig.RecentlyAdded(id, HomeRowViewOptions()), + ) + } + val rowConfig = + listOf( + HomeRowConfigDisplay( + context.getString(R.string.continue_watching), + HomeRowConfig.ContinueWatching( + prefs.combineContinueNext, + HomeRowViewOptions(), + ), + ), + ) + includedIds + _state.update { + it.copy(rows = rowConfig) + } + + fetchRowData() + } + } + + fun updateBackdrop(item: BaseItem) { + viewModelScope.launchIO { + backdropService.submit(item) + } + } + + private suspend fun fetchRowData() { + val limit = 6 + val rows = + serverRepository.currentUserDto.value?.let { userDto -> + val prefs = userPreferencesService.getCurrent().appPreferences.homePagePreferences + state.value.rows + .map { it.config } + .map { row -> + // TODO parallelize + when (row) { + is HomeRowConfig.ContinueWatching -> { + val resume = latestNextUpService.getResume(userDto.id, limit, true) + val nextUp = + latestNextUpService.getNextUp( + userDto.id, + limit, + 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, + ), + ) + } else { + if (resume.isNotEmpty()) { + add( + HomeRowLoadingState.Success( + title = context.getString(R.string.continue_watching), + items = resume, + ), + ) + } + if (nextUp.isNotEmpty()) { + add( + HomeRowLoadingState.Success( + title = context.getString(R.string.next_up), + items = nextUp, + ), + ) + } + } + } + watching + } + + is HomeRowConfig.Genres -> { + val request = + GetGenresRequest( + parentId = row.parentId, + userId = userDto.id, + limit = limit, + ) + val items = + GetGenresRequestHandler + .execute(api, request) + .content.items + .map { BaseItem(it, false) } + val name = + _state.value.libraries + .firstOrNull { it.itemId == row.parentId } + ?.name + val title = + name?.let { context.getString(R.string.genres_in, it) } + ?: context.getString(R.string.genres) + listOf(HomeRowLoadingState.Success(title, items)) + } + + is HomeRowConfig.RecentlyAdded -> { + val name = + _state.value.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 request = + GetLatestMediaRequest( + fields = SlimItemFields, + imageTypeLimit = 1, + parentId = row.parentId, + groupItems = true, + limit = limit, + isPlayed = null, // Server will handle user's preference + ) + latestNextUpService.loadLatest(listOf(LatestData(title, request))) + } + + is HomeRowConfig.RecentlyReleased -> { + TODO() + } + } + }.flatten() + } + rows?.let { rows -> + _state.update { + it.copy(loading = LoadingState.Success, rowData = rows) + } + } + } + + private fun List.move( + direction: MoveDirection, + index: Int, + ): List = + toMutableList().apply { + if (direction == MoveDirection.DOWN) { + val down = this[index] + val up = this[index + 1] + set(index, up) + set(index + 1, down) + } else { + val up = this[index] + val down = this[index - 1] + set(index - 1, up) + set(index, down) + } + } + + fun moveRow( + direction: MoveDirection, + index: Int, + ) { + _state.update { + val rows = it.rows.move(direction, index) + // TODO would be more efficient to move rowData, but uncombined continue watching is two rows +// val rowData = it.rowData.move(direction, index) + it.copy( + loading = LoadingState.Loading, + rows = rows, + ) + } + viewModelScope.launchIO { fetchRowData() } + } + + fun deleteRow(index: Int) { + _state.update { + val rows = it.rows.toMutableList().apply { removeAt(index) } + val rowData = it.rowData.toMutableList().apply { removeAt(index) } + it.copy( + rows = rows, + rowData = rowData, + ) + } + } + } + +data class HomePageSettingsState( + val loading: LoadingState, + val rows: List, + val rowData: List, + val libraries: List, +) { + companion object { + val EMPTY = + HomePageSettingsState( + LoadingState.Pending, + listOf(), + listOf(), + listOf(), + ) + } +} + +data class Library( + val itemId: UUID, + val name: String, + val collectionType: CollectionType, +) + +val settingsWidth = 300.dp + +@Composable +fun HomePageSettings( + modifier: Modifier, + viewModel: HomePageSettingsViewModel = hiltViewModel(), +) { + val state by viewModel.state.collectAsState() + val listState = rememberLazyListState() + var destination by remember { mutableStateOf(HomePageSettingsDestination.RowList) } + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + modifier = modifier, + ) { + HomePageContent( + loadingState = state.loading, + homeRows = state.rowData, + onClickItem = { _, _ -> }, + onLongClickItem = { _, _ -> }, + onClickPlay = { _, _ -> }, + showClock = false, + onUpdateBackdrop = viewModel::updateBackdrop, + listState = listState, + modifier = Modifier.fillMaxHeight().weight(1f), + ) + Box( + modifier = + Modifier + .width(settingsWidth) + .fillMaxHeight() + .background(color = MaterialTheme.colorScheme.surface), + ) { + when (destination) { + HomePageSettingsDestination.RowList -> { + HomePageRowList( + state = state, + onClickAdd = { destination = HomePageSettingsDestination.ChooseLibrary }, + onClickMove = viewModel::moveRow, + onClickDelete = viewModel::deleteRow, + modifier = Modifier.fillMaxSize(), + ) + } + + is HomePageSettingsDestination.ChooseLibrary -> { + TODO() + } + + is HomePageSettingsDestination.ChooseRow -> { + TODO() + } + + is HomePageSettingsDestination.RowSettings -> { + TODO() + } + } + } + } +} diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomePageSettingsDestination.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomePageSettingsDestination.kt new file mode 100644 index 00000000..3ebdc166 --- /dev/null +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/main/settings/HomePageSettingsDestination.kt @@ -0,0 +1,17 @@ +package com.github.damontecres.wholphin.ui.main.settings + +import com.github.damontecres.wholphin.data.model.HomeRowConfigDisplay + +sealed interface HomePageSettingsDestination { + data object RowList : HomePageSettingsDestination + + data object ChooseLibrary : HomePageSettingsDestination + + data class ChooseRow( + val library: Library, + ) : HomePageSettingsDestination + + data class RowSettings( + val row: HomeRowConfigDisplay, + ) : HomePageSettingsDestination +} diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/nav/Destination.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/nav/Destination.kt index 426d5328..d00416cf 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/nav/Destination.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/nav/Destination.kt @@ -33,6 +33,9 @@ sealed class Destination( val id: Long = 0L, ) : Destination() + @Serializable + data object HomeSettings : Destination(true) + @Serializable data class Settings( val screen: PreferenceScreenOption, 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 43b8841d..b4ef4575 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 @@ -32,6 +32,7 @@ import com.github.damontecres.wholphin.ui.detail.series.SeriesOverview import com.github.damontecres.wholphin.ui.discover.DiscoverPage import com.github.damontecres.wholphin.ui.main.HomePage import com.github.damontecres.wholphin.ui.main.SearchPage +import com.github.damontecres.wholphin.ui.main.settings.HomePageSettings import com.github.damontecres.wholphin.ui.playback.PlaybackPage import com.github.damontecres.wholphin.ui.preferences.PreferencesPage import com.github.damontecres.wholphin.ui.setup.InstallUpdatePage @@ -60,6 +61,10 @@ fun DestinationContent( ) } + is Destination.HomeSettings -> { + HomePageSettings(modifier) + } + is Destination.PlaybackList, is Destination.Playback, -> { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c83a3b63..8fa26d53 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -462,6 +462,8 @@ Request in 4K AV1 software decoding MPV is now the default player except for HDR.\nYou can change this in settings. + Add row + Genres in %1$s Disabled