mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Handle adding rows & back handling
This commit is contained in:
parent
6d53869180
commit
5dcdde36c3
7 changed files with 270 additions and 39 deletions
|
|
@ -13,29 +13,33 @@ import java.util.UUID
|
|||
|
||||
@Serializable
|
||||
sealed class HomeRowConfig {
|
||||
abstract val id: UUID
|
||||
abstract val viewOptions: HomeRowViewOptions
|
||||
|
||||
@Serializable
|
||||
data class ContinueWatching(
|
||||
override val id: UUID,
|
||||
val combined: Boolean,
|
||||
override val viewOptions: HomeRowViewOptions,
|
||||
) : HomeRowConfig()
|
||||
|
||||
@Serializable
|
||||
data class RecentlyAdded(
|
||||
override val id: UUID,
|
||||
val parentId: UUID,
|
||||
override val viewOptions: HomeRowViewOptions,
|
||||
) : HomeRowConfig()
|
||||
|
||||
@Serializable
|
||||
data class RecentlyReleased(
|
||||
override val id: UUID,
|
||||
val parentId: UUID,
|
||||
override val viewOptions: HomeRowViewOptions,
|
||||
) : HomeRowConfig()
|
||||
|
||||
@Serializable
|
||||
data class Genres(
|
||||
val genreId: UUID,
|
||||
override val id: UUID,
|
||||
val parentId: UUID,
|
||||
override val viewOptions: HomeRowViewOptions,
|
||||
) : HomeRowConfig()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
package com.github.damontecres.wholphin.ui.main.settings
|
||||
|
||||
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.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.remember
|
||||
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.unit.dp
|
||||
import androidx.tv.material3.ListItem
|
||||
import androidx.tv.material3.Text
|
||||
import com.github.damontecres.wholphin.ui.ifElse
|
||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||
|
||||
@Composable
|
||||
fun HomePageLibraryList(
|
||||
libraries: List<Library>,
|
||||
onClick: (Library) -> Unit,
|
||||
modifier: Modifier,
|
||||
firstFocus: FocusRequester = remember { FocusRequester() },
|
||||
) {
|
||||
LaunchedEffect(Unit) { firstFocus.tryRequestFocus() }
|
||||
Column(modifier = modifier) {
|
||||
Text(
|
||||
text = "Add row for...",
|
||||
)
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier =
|
||||
modifier
|
||||
.fillMaxHeight()
|
||||
.focusRestorer(firstFocus),
|
||||
) {
|
||||
itemsIndexed(libraries) { index, library ->
|
||||
ListItem(
|
||||
selected = false,
|
||||
headlineContent = {
|
||||
Text(library.name)
|
||||
},
|
||||
onClick = { onClick.invoke(library) },
|
||||
modifier = Modifier.ifElse(index == 0, Modifier.focusRequester(firstFocus)),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
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.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.remember
|
||||
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
|
||||
|
||||
@Composable
|
||||
fun HomePageLibraryRowTypeList(
|
||||
library: Library,
|
||||
onClick: (LibraryRowType) -> Unit,
|
||||
modifier: Modifier,
|
||||
firstFocus: FocusRequester = remember { FocusRequester() },
|
||||
) {
|
||||
LaunchedEffect(Unit) { firstFocus.tryRequestFocus() }
|
||||
Column(modifier = modifier) {
|
||||
Text(
|
||||
text = "Add row for ${library.name}",
|
||||
)
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier =
|
||||
modifier
|
||||
.fillMaxHeight()
|
||||
.focusRestorer(firstFocus),
|
||||
) {
|
||||
itemsIndexed(LibraryRowType.entries) { index, rowType ->
|
||||
ListItem(
|
||||
selected = false,
|
||||
headlineContent = {
|
||||
Text(
|
||||
text = stringResource(rowType.stringId),
|
||||
)
|
||||
},
|
||||
onClick = { onClick.invoke(rowType) },
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.ifElse(index == 0, Modifier.focusRequester(firstFocus)),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class LibraryRowType(
|
||||
@param:StringRes val stringId: Int,
|
||||
) {
|
||||
RECENTLY_ADDED(R.string.recently_added),
|
||||
RECENTLY_RELEASED(R.string.recently_released),
|
||||
GENRES(R.string.genres),
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@ 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
|
||||
|
|
@ -31,6 +30,7 @@ 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
|
||||
|
|
@ -52,18 +52,18 @@ fun HomePageRowList(
|
|||
) {
|
||||
Column(modifier = modifier) {
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier =
|
||||
modifier
|
||||
.fillMaxHeight()
|
||||
.focusRestorer(firstFocus),
|
||||
) {
|
||||
itemsIndexed(state.rows) { index, row ->
|
||||
itemsIndexed(state.rows, key = { _, row -> row.config.id }) { index, row ->
|
||||
HomeRowConfigContent(
|
||||
config = row,
|
||||
moveUpAllowed = index > 0,
|
||||
moveDownAllowed = index != state.rows.lastIndex,
|
||||
deleteAllowed = row.config !is HomeRowConfig.ContinueWatching,
|
||||
onClickMove = { onClickMove.invoke(it, index) },
|
||||
onClickDelete = { onClickDelete.invoke(index) },
|
||||
modifier =
|
||||
|
|
@ -91,6 +91,7 @@ fun HomeRowConfigContent(
|
|||
config: HomeRowConfigDisplay,
|
||||
moveUpAllowed: Boolean,
|
||||
moveDownAllowed: Boolean,
|
||||
deleteAllowed: Boolean,
|
||||
onClickMove: (MoveDirection) -> Unit,
|
||||
onClickDelete: () -> Unit,
|
||||
modifier: Modifier,
|
||||
|
|
@ -108,14 +109,17 @@ fun HomeRowConfigContent(
|
|||
.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),
|
||||
modifier =
|
||||
Modifier
|
||||
.weight(1f)
|
||||
.padding(start = 4.dp),
|
||||
)
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
|
|
@ -141,7 +145,7 @@ fun HomeRowConfigContent(
|
|||
}
|
||||
Button(
|
||||
onClick = onClickDelete,
|
||||
enabled = true,
|
||||
enabled = deleteAllowed,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Delete,
|
||||
|
|
|
|||
|
|
@ -1,15 +1,18 @@
|
|||
package com.github.damontecres.wholphin.ui.main.settings
|
||||
|
||||
import android.content.Context
|
||||
import androidx.activity.compose.BackHandler
|
||||
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.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
|
|
@ -96,7 +99,11 @@ class HomePageSettingsViewModel
|
|||
?: context.getString(R.string.recently_added)
|
||||
HomeRowConfigDisplay(
|
||||
title,
|
||||
HomeRowConfig.RecentlyAdded(id, HomeRowViewOptions()),
|
||||
HomeRowConfig.RecentlyAdded(
|
||||
UUID.randomUUID(),
|
||||
id,
|
||||
HomeRowViewOptions(),
|
||||
),
|
||||
)
|
||||
}
|
||||
val rowConfig =
|
||||
|
|
@ -104,6 +111,7 @@ class HomePageSettingsViewModel
|
|||
HomeRowConfigDisplay(
|
||||
context.getString(R.string.continue_watching),
|
||||
HomeRowConfig.ContinueWatching(
|
||||
UUID.randomUUID(),
|
||||
prefs.combineContinueNext,
|
||||
HomeRowViewOptions(),
|
||||
),
|
||||
|
|
@ -274,6 +282,66 @@ class HomePageSettingsViewModel
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun addRow(
|
||||
library: Library,
|
||||
rowType: LibraryRowType,
|
||||
) {
|
||||
viewModelScope.launchIO {
|
||||
val newRow =
|
||||
when (rowType) {
|
||||
LibraryRowType.RECENTLY_ADDED -> {
|
||||
val title =
|
||||
library.name.let { context.getString(R.string.recently_added_in, it) }
|
||||
HomeRowConfigDisplay(
|
||||
title,
|
||||
HomeRowConfig.RecentlyAdded(
|
||||
UUID.randomUUID(),
|
||||
library.itemId,
|
||||
HomeRowViewOptions(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
LibraryRowType.RECENTLY_RELEASED -> {
|
||||
val title =
|
||||
library.name.let {
|
||||
context.getString(
|
||||
R.string.recently_released_in,
|
||||
it,
|
||||
)
|
||||
}
|
||||
HomeRowConfigDisplay(
|
||||
title,
|
||||
HomeRowConfig.RecentlyReleased(
|
||||
UUID.randomUUID(),
|
||||
library.itemId,
|
||||
HomeRowViewOptions(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
LibraryRowType.GENRES -> {
|
||||
val title = library.name.let { context.getString(R.string.genres_in, it) }
|
||||
HomeRowConfigDisplay(
|
||||
title,
|
||||
HomeRowConfig.Genres(
|
||||
UUID.randomUUID(),
|
||||
library.itemId,
|
||||
HomeRowViewOptions(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
_state.update {
|
||||
it.copy(
|
||||
loading = LoadingState.Loading,
|
||||
rows = it.rows.toMutableList().apply { add(newRow) },
|
||||
)
|
||||
}
|
||||
fetchRowData()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class HomePageSettingsState(
|
||||
|
|
@ -293,6 +361,7 @@ data class HomePageSettingsState(
|
|||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
data class Library(
|
||||
val itemId: UUID,
|
||||
val name: String,
|
||||
|
|
@ -309,10 +378,66 @@ fun HomePageSettings(
|
|||
val state by viewModel.state.collectAsState()
|
||||
val listState = rememberLazyListState()
|
||||
var destination by remember { mutableStateOf<HomePageSettingsDestination>(HomePageSettingsDestination.RowList) }
|
||||
|
||||
BackHandler(destination is HomePageSettingsDestination.ChooseRowType) {
|
||||
destination = HomePageSettingsDestination.ChooseLibrary
|
||||
}
|
||||
BackHandler(destination is HomePageSettingsDestination.ChooseLibrary) {
|
||||
destination = HomePageSettingsDestination.RowList
|
||||
}
|
||||
BackHandler(destination is HomePageSettingsDestination.RowSettings) {
|
||||
destination = HomePageSettingsDestination.RowList
|
||||
}
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = modifier,
|
||||
) {
|
||||
Box(
|
||||
modifier =
|
||||
Modifier
|
||||
.width(settingsWidth)
|
||||
.fillMaxHeight()
|
||||
.background(color = MaterialTheme.colorScheme.surface),
|
||||
) {
|
||||
val destModifier =
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.padding(4.dp)
|
||||
when (val dest = destination) {
|
||||
HomePageSettingsDestination.RowList -> {
|
||||
HomePageRowList(
|
||||
state = state,
|
||||
onClickAdd = { destination = HomePageSettingsDestination.ChooseLibrary },
|
||||
onClickMove = viewModel::moveRow,
|
||||
onClickDelete = viewModel::deleteRow,
|
||||
modifier = destModifier,
|
||||
)
|
||||
}
|
||||
|
||||
is HomePageSettingsDestination.ChooseLibrary -> {
|
||||
HomePageLibraryList(
|
||||
libraries = state.libraries,
|
||||
onClick = { destination = HomePageSettingsDestination.ChooseRowType(it) },
|
||||
modifier = destModifier,
|
||||
)
|
||||
}
|
||||
|
||||
is HomePageSettingsDestination.ChooseRowType -> {
|
||||
HomePageLibraryRowTypeList(
|
||||
library = dest.library,
|
||||
onClick = {
|
||||
viewModel.addRow(dest.library, it)
|
||||
destination = HomePageSettingsDestination.RowList
|
||||
},
|
||||
modifier = destModifier,
|
||||
)
|
||||
}
|
||||
|
||||
is HomePageSettingsDestination.RowSettings -> {
|
||||
TODO()
|
||||
}
|
||||
}
|
||||
}
|
||||
HomePageContent(
|
||||
loadingState = state.loading,
|
||||
homeRows = state.rowData,
|
||||
|
|
@ -322,38 +447,10 @@ fun HomePageSettings(
|
|||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
.weight(1f),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ sealed interface HomePageSettingsDestination {
|
|||
|
||||
data object ChooseLibrary : HomePageSettingsDestination
|
||||
|
||||
data class ChooseRow(
|
||||
data class ChooseRowType(
|
||||
val library: Library,
|
||||
) : HomePageSettingsDestination
|
||||
|
||||
|
|
|
|||
|
|
@ -464,6 +464,7 @@
|
|||
<string name="upgrade_mpv_toast">MPV is now the default player except for HDR.\nYou can change this in settings.</string>
|
||||
<string name="add_row">Add row</string>
|
||||
<string name="genres_in">Genres in %1$s</string>
|
||||
<string name="recently_released_in">Recently released in %1$s</string>
|
||||
|
||||
<string-array name="theme_song_volume">
|
||||
<item>Disabled</item>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue